如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
推断为int
(t
的类型为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:
两个签名都返回相同的内容:
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的报价是错误的吗?
答案 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
是参考,那么它可能就会出现。