为什么std :: forward有两个签名?

时间:2016-11-17 14:20:00

标签: c++ c++11 stl rvalue-reference rvalue

cplusplus.com所述,std::forward有两个签名:

template <class T> T&& forward (typename remove_reference<T>::type& arg) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& arg) noexcept;

std::forward的典型用法是在将参数传递给其他函数时保留rvalueness。让我们用一个例子说明这一点:

void overloaded(int &)  { std::cout << "lvalue"; }
void overloaded(int &&) { std::cout << "rvalue"; }

template <typename T>
void fwd(T && t)
{
  overloaded(std::forward<T>(t));
}

当我们致电fwd(0)时,T推断为intt的类型为int &&)。然后我们打电话给std::forward<int>(t)。该调用的结果是int &&类型的表达式,因此选择了overloaded函数的第二个版本,程序将“rvalue”打印到标准输出。

当我们调用fwd(i)(其中i是某个int变量)时,T推导为int&t的类型为int &)。然后我们打电话给std::forward<int&>(t)。该调用的结果(在应用引用折叠规则之后)是int &类型的表达式,因此选择了overloaded函数的第一个版本,程序将“左值”打印到标准输出。

在这两种情况下,我们使用std::forward的第一个重载(采用typename remove_reference<T>::type& arg的重载)。这是因为即使t的类型是int &&,它也会绑定到左值引用(因为“rvalue对某事物的引用”的命名变量本身是左值,而左值不能绑定到右值引用)。

问题1:

std::forward的第二次重载是什么?你能想到一些实际的例子吗,它使用rvalue reference引用arg的重载?

问题2:

cplusplus.com说:

  

两个签名都返回相同的内容:

static_cast<decltype(arg)&&>(arg)

我遇到的问题是,我很确定这是错的。当我们尝试从std::forward的第一个重载返回时,我们得到一个编译错误。

当使用fwd rvalue调用int时,它会使用std::forward调用T = int的第一次重载。然后,decltype(arg)将变为int&,因此static_cast<decltype(arg)&&>(arg)将折叠为static_cast<int&>(arg)。但是返回类型是int &&,我们得到编译错误:

cannot bind ‘std::remove_reference<int>::type {aka int}’ lvalue to ‘int&&’

std::forward的重载版本都应返回static_cast<T&&>(arg)。我是对的吗?

您认为cplusplus.com的报价是错误的吗?

1 个答案:

答案 0 :(得分:1)

wmic process where "name='WMIC.exe'" get parentprocessid

有点做作;但想象一下,你有一些工厂可能产生class Foo {}; auto f = [](){ return Foo{}; }; auto g = []()->Foo&{ static Foo x; return x; }; template<class T> std::false_type is_rvalue( T& ) { return {}; } template<class T> std::true_type is_rvalue( T&& ) { return {}; } template<class T, class F> auto test( F&& f ) { return is_rvalue( std::forward<T>( f() ) ); } int main() { std::cout << test<Foo>(f) << "," << test<Foo&>(g) << "\n"; } Foo取决于一些不重要的细节,但你知道你希望根据第二种类型转发它{ {1}}到Foo&。您知道,如果T不是参考,那么它就不会产生T&&,但如果T是参考,那么它可能就会出现。