Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 右值模板参数隐式用作左值,std::转发工作_C++_Templates_C++11_Rvalue Reference_Perfect Forwarding - Fatal编程技术网

C++ 右值模板参数隐式用作左值,std::转发工作

C++ 右值模板参数隐式用作左值,std::转发工作,c++,templates,c++11,rvalue-reference,perfect-forwarding,C++,Templates,C++11,Rvalue Reference,Perfect Forwarding,关于std::forward的用法让我感到困惑。这是我编辑的版本: #include <iostream> #include <memory> #include <utility> using namespace std; struct A{ A(int&& n) { cout << "rvalue overload, n=" << n << "\n"; } A(int& n) {

关于std::forward的用法让我感到困惑。这是我编辑的版本:

#include <iostream>
#include <memory>
#include <utility>
using namespace std;

struct A{
    A(int&& n) { cout << "rvalue overload, n=" << n << "\n"; }
    A(int& n)  { cout << "lvalue overload, n=" << n << "\n"; }
};

template<typename> void template_type_dumper();

template<class T, class U>
unique_ptr<T> make_unique(U&& u){
    //Have a "fingerprint" of what function is being called
    static int dummyvar;
    cout<<"address of make_unique::dummyvar: "<<&dummyvar<<endl;
    //g++ dumps two warnings here, which reveal what exact type is passed as template parameter
    template_type_dumper<decltype(u)>;
    template_type_dumper<U>;

    return unique_ptr<T>(new T(forward<U>(u)));
}

int main()
{
    unique_ptr<A> p1 = make_unique<A>(2); // rvalue
    int i = 1;
    unique_ptr<A> p2 = make_unique<A>(i); // lvalue
}
关于引用模板\U type\U转储程序的警告显示,在第一个实例化中,decltypeu=int&&和U=int,对于第二个decltypeu=int&和U=int&

很明显,正如预期的那样,有两种不同的实例化,但我的问题是:

std::forward如何在这里工作?在第一个实例化中,它的模板参数显式为U=int,它如何知道必须返回右值引用?如果我改为指定U&&会发生什么? 声明make_unique以获取右值引用。为什么u可以是左值引用?有没有什么特别的规定我不知道? 声明make_unique以获取右值引用。为什么u可以是左值引用?有没有什么特别的规定我不知道

声明make_unique以获取引用。这是一种什么样的参照。如果传递了foo类型的左值,U将被推断为foo&并且U&&将成为foo&因为引用折叠规则基本上是这样的,将左值引用与另一个引用相结合总是会生成左值引用;组合两个右值引用将生成一个右值引用。如果传递了foo类型的右值,则U将被推断为foo,U&&是foo&&

这是支持完美转发的因素之一:使用U&&可以同时使用左值和右值,并且U被推导出与适当的值类别相匹配。然后使用std::forward,您可以转发保留相同值类别的值:在第一种情况下,您得到std::forward,它转发左值,在第二种情况下,您得到std::forward,它转发右值

在第一个实例化中,它的模板参数显式为U=int,它如何知道必须返回右值引用

因为std::forward的返回类型总是T&&。如果传递int,则返回int&&。如果传递int&它将再次返回int&因为引用折叠规则

如果我改为指定U&&会发生什么

您将使用std::forward,引用折叠规则使int&&&仍然是右值引用:int&&&

声明make_unique以获取右值引用。为什么u可以是左值引用?有没有什么特别的规定我不知道

声明make_unique以获取引用。这是一种什么样的参照。如果传递了foo类型的左值,U将被推断为foo&并且U&&将成为foo&因为引用折叠规则基本上是这样的,将左值引用与另一个引用相结合总是会生成左值引用;组合两个右值引用将生成一个右值引用。如果传递了foo类型的右值,则U将被推断为foo,U&&是foo&&

这是支持完美转发的因素之一:使用U&&可以同时使用左值和右值,并且U被推导出与适当的值类别相匹配。然后使用std::forward,您可以转发保留相同值类别的值:在第一种情况下,您得到std::forward,它转发左值,在第二种情况下,您得到std::forward,它转发右值

在第一个实例化中,它的模板参数显式为U=int,它如何知道必须返回右值引用

因为std::forward的返回类型总是T&&。如果传递int,则返回int&&。如果传递int&它将再次返回int&因为引用折叠规则

如果我改为指定U&&会发生什么


您将使用std::forward,引用折叠规则使int&&&仍然是右值引用:int&。

您丢失了。您丢失了。遗憾的是,大多数在线文章在解释右值引用时似乎更关注移动语义,而不是此引用折叠机制,这基本上回答了我所有的问题。U是一种类型,所以它没有真正的价值类别。相反,U被推断为非引用或左值引用类型。@KerrekSB I修正了措辞:@LorenzoPistone:Move语义是最常用的。引用折叠等描述起来要复杂得多,只有在编写模板转发函数时才有用。遗憾的是,大多数在线文章在解释右值引用时似乎更多地关注移动语义,而不是这个引用折叠机制,它基本上回答了我所有的问题。U是一个类型,所以它实际上没有一个值类别。相反,U被推断为非引用或左值引用类型。@KerrekSB I修正了措辞:@LorenzoPistone:Move语义是最常用的。引用折叠等描述起来要复杂得多,只有在编写模板转发函数时才有用。这不是每个人都会做的。
address of make_unique::dummyvar: 0x6021a4
rvalue overload, n=2
address of make_unique::dummyvar: 0x6021a8
lvalue overload, n=1