#转发(std::forward)
定义于头文件<utility>中:
template< typename T >
T&& forward( typename std::remove_reference<T>::type& t ) noexcept ; (1) (C++11 - C++14)template< typename T >
constexpr T&& forward( typename std::remove_reference<T>::type& t ) noexcept ; (1) (C++14 - )template< typename T >
T&& forward( typename std::remove_reference<T>::type&& t ) noexcept ; (2) (C++11 - C++14)template< typename T >
constexpr T&& forward( typename std::remove_reference<T>::type&& t ) noexcept ; (2) (C++14 - )在函数模板中按下面的方式使用forward调用函数时,转发传递过来的实参及其值类型(value category)给另外一个函数。
比如,如果wrapper函数代码如下,该模板将按下面描述的那样实例化:
template<class T>
void wrapper(T&& arg)
{
foo(std::forward<T>(arg)); // Forward a single argument.
}- 当传递给
wrapper的是string类型的右值时,T会被推演为string(而不是string&,const string&,或string&&),同时forward会确保传递给函数foo的是一个右值。 - 当传递给
wrapper的是const string类型左值时,T会被推演为const string&,同时forward会确保传递给函数foo的是一个常量左值引用。 - 当传递给
wrapper的是string类型左值时,T会被推演为string&,同时forward会确保传递给函数foo的是一个非常量左值引用。
##注意
试图把右值当作左值转发,将会产生一个编译时错误,如用左值引用类型T实例化声明(2)就是如此。
T&&作为函数形参的特殊规则 —— C++11新引入了“引用折叠”(reference collapsing),请参考模板实参推演。
##参数
t - 待转发的对象
##返回值
static_cast<T&&>(t)
##异常
noexcept指定: noexcept
即不允许跑出异常。
##例子
下面是一个将参数完美转发给T类型的构造函数实参的例子。同时也展示了可变参数的完美转发。
#include <iostream>
#include <memory>
#include <utility>
#include <array>
struct A {
A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; }
A(int& n) { std::cout << "lvalue overload, n=" << n << "\n"; }
};
class B {
public:
template<class T1, class T2, class T3>
B(T1&& t1, T2&& t2, T3&& t3) :
a1_{std::forward<T1>(t1)},
a2_{std::forward<T2>(t2)},
a3_{std::forward<T3>(t3)}
{
}
private:
A a1_, a2_, a3_;
};
template<class T, class U>
std::unique_ptr<T> make_unique1(U&& u)
{
return std::unique_ptr<T>(new T(std::forward<U>(u)));
}
template<class T, class... U>
std::unique_ptr<T> make_unique(U&&... u)
{
return std::unique_ptr<T>(new T(std::forward<U>(u)...));
}
int main()
{
auto p1 = make_unique1<A>(2); // rvalue
int i = 1;
auto p2 = make_unique1<A>(i); // lvalue
std::cout << "B\n";
auto t = make_unique<B>(2, i, 3);
return 0;
}输出为:
rvalue overload, n=2
lvalue overload, n=1
B
rvalue overload, n=2
lvalue overload, n=1
rvalue overload, n=3##复杂度
常量级
##另见
- move(C++11) 强制转换为右值引用(函数模板)
- move_if_noexcept(C++11) 当移动构造函数未抛出异常时强制转换为右值引用(函数模板)