我知道转发引用是“对cv不合格模板参数的右值引用”,例如
template <class T> void foo(T&& );
Run Code Online (Sandbox Code Playgroud)
这意味着上述函数可以同时使用l值和r值参考。
我有些不懂的事,例如
template <class T>
class A
{
template <class U>
void foo(T&& t, U&& u)
{
T t2( std::forward(t) ); // or should it be std::move(t)? is T&& forwarding or r-value reference
U u2( std::forward(u) ); // or should it be std::move(u)? I believe U&& is forwarding reference
}
};
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,T &&和U &&都是转发参考吗?
我写了一些代码进行测试(VS2015编译器):
class A
{
public:
A(){};
A(const A& rhs)
{
std::cout << "calling 'const A&' l-value" << std::endl; …Run Code Online (Sandbox Code Playgroud) 让我们foo的功能:
template< typename T >
void foo( T&& a ){}
Run Code Online (Sandbox Code Playgroud)
T以下调用将推断出什么类型foo:
foo( 0 ); // is T here int or int&& ?
int a = 0;
foo( a ); // is T here int or int& ?
Run Code Online (Sandbox Code Playgroud) #include <type_traits>
template<typename T>
void f(const T&)
{
static_assert(std::is_array_v<T>); // ok
}
template<typename T>
void g(T&&)
{
static_assert(std::is_array_v<T>); // error
}
int main()
{
char arr[8];
f(arr); // ok
g(arr); // error
}
Run Code Online (Sandbox Code Playgroud)
我的编译器是clang 7.0 with -std=c++17.
为什么通用引用不适用于数组?
在我的下面的代码中,我有一个接受"通用引用"(F&&)的函数.该函数还有一个内部类,它接受F&&构造函数中的对象.是F&&仍然在这一点上通用的参考?即F仍然被认为是推断类型?
换句话说,我应该使用std::forward<F>或std::move在构造函数初始化列表中?
#include "tbb/task.h"
#include <iostream>
#include <future>
template<class F>
auto Async(F&& f) -> std::future<decltype(f())>
{
typedef decltype(f()) result_type;
struct Task : tbb::task
{
Task(F&& f) : f_(std::forward<F>(f)) {} // is forward correct here?
virtual tbb::task* execute()
{
f_();
return nullptr;
}
std::packaged_task<result_type()> f_;
};
auto task = new (tbb::task::allocate_root()) Task(std::forward<F>(f));
tbb::task::enqueue(*task);
return task->f_.get_future();
}
int main()
{
Async([]{ std::cout << "Hi" << std::endl; }).get();
}
Run Code Online (Sandbox Code Playgroud)
c++ forwarding forward perfect-forwarding forwarding-reference
我有一个带有push函数的并发队列的模板化实现,如下所示:
template <typename T>
class concurrent_queue
{
public:
// other code...
void push(const T& item)
{
std::unique_lock<std::mutex> mlock(mutex);
queue.push_back(std::forward(item));
mlock.unlock();
notEmpty.notify_one();
}
private:
std::deque<T> queue;
std::mutex mutex;
// other stuff...
};
Run Code Online (Sandbox Code Playgroud)
稍后,我实例化它并像这样使用它:
concurrent_queue<c2Type> m_queue; // c2 type is some struct declared previously
Run Code Online (Sandbox Code Playgroud)
然后我尝试推送队列上的项目,我得到上面提到的编译器错误:
c2Type c2message;
// fill in the message struct...
m_queue.push(c2message);
Run Code Online (Sandbox Code Playgroud)
我之前成功地使用了队列,作为存储std::function对象的线程池实现的一部分.我不明白为什么在这种情况下不能推断出类型.有什么想法吗?
我有一个我正在编写的类,它将为其中一个构造函数采用特殊类型,它可以是符合我要求的任何类型.我遇到了这个模板化构造函数导致我的副本并将构造函数移动为非法重载的问题!
我的班级是这样的:
template<typename ... Types>
class myclass{
public:
myclass(const myclass &other){/* copy constructor */}
myclass(myclass &&other){/* move constructor */}
template<typename Special>
myclass(Special &&arg){/* stops copy/move implementations */}
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个限制?
请考虑以下代码:
template <class F, class... Args>
void function(F&& f, Args&&... args)
{
using type1 = decltype(std::forward<F>(f)(std::forwards<Args>(args)...));
using type2 = decltype(/*equivalent expression but only using types */);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在所有情况下使用type2相同的方法,type1但只使用decltype表达式中的类型,或者换句话说只使用F和Args而不是f和args?
template<typename T>
void f(T&& n)
{
++n; // ok to modify a const object, why?
}
template<typename T>
void g()
{
int n{};
f<const T&>(n);
}
int main()
{
g<int&>();
}
Run Code Online (Sandbox Code Playgroud)
如上面的代码所示.我的问题是:
为什么通用引用不保持其参数的常量?
这两者有区别吗
struct S;
int& foo(S&);
auto&& bar1(S& s) {
return foo(s);
}
decltype(auto) bar2(S& s) {
return foo(s);
}
Run Code Online (Sandbox Code Playgroud)
对于编译器?我一直在这样decltype(auto)的情况下使用,但似乎auto&&可以解决问题。这是巧合还是两者完全相同?
我在学习通用(转发)参考时发现了这个问题。代码如下。
\n#include <iostream> // std::cout\n\n#include <type_traits>\n\ntemplate <class T> // deductions among universal reference\nvoid fun(T &&b) // fold reference, maintain const\n{\n std::cout << b << " ";\n std::cout << std::is_const<T>::value << " ";\n std::cout << std::is_lvalue_reference<T>::value << " ";\n std::cout << std::is_rvalue_reference<T>::value << std::endl;\n}\n\nint main()\n{\n int a = 1;\n fun(a); // lvalue: T=int&\n fun(std::move(a)); // rvalue: T=int\n\n const int ca = 1;\n fun(ca); // const_lvalue: T=int& \xef\xbc\x88why no const?\xef\xbc\x89\n fun(std::move(ca)); // const_rvalue: T=const int\n\n int &la = a;\n fun(la); // …Run Code Online (Sandbox Code Playgroud)