std::forward
STD:向前
Defined in header | | |
---|---|---|
template< class T > T&& forward( typename std::remove_reference<T>::type& t ) noexcept; | (1) | (since C++11) (until C++14) |
template< class T > constexpr T&& forward( typename std::remove_reference<T>::type& t ) noexcept; | (1) | (since C++14) |
template< class T > T&& forward( typename std::remove_reference<T>::type&& t ) noexcept; | (2) | (since C++11) (until C++14) |
template< class T > constexpr T&& forward( typename std::remove_reference<T>::type&& t ) noexcept; | (2) | (since C++14) |
1%29将lvalue作为lvalue或rvalue转发,这取决于T。
何时t
是转发参考%28a函数参数,它是对cv-不限定函数模板参数%29的rvalue引用,此重载使用价值范畴它在传递给调用函数时已经完成了。
例如,如果在包装器中使用,如以下所示,模板的行为如下所述:
二次
template<class T>
void wrapper(T&& arg)
{
// arg is always lvalue
foo(std::forward<T>(arg) // Forward as lvalue or as rvalue, depending on T
}
二次
- 如果打电话到
wrapper()
传递rvaluestd::string
,然后T
推导成std::string
%28不std::string&
,,,const std::string&
,或std::string&&
%29,和std::forward
确保将rvalue引用传递给foo
...
- 如果打电话到
wrapper()
传递一个Const值std::string
,然后T
推导成const std::string&
,和std::forward
确保将const lvalue引用传递给foo
...
- 如果打电话到
wrapper()
传递一个非条件值。std::string
,然后T
推导成std::string&
,和std::forward
确保将非Const lvalue引用传递给foo
...
2%29将rvalue转发为rvalue,并禁止将rvalue转发为lvalue。
这种重载使得可以转发表达式%28的结果,例如函数调用%29,它可以是rvalue或lvalue,作为转发引用参数的原始值类别。
例如,如果包装器不只是转发其参数,而是对参数调用成员函数,并转发其结果:
二次
// transforming wrapper
template<class T>
void wrapper(T&& arg)
{
foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get())
}
二次
可能是Arg的类型。
二次
struct Arg
{
int i = 1;
int get() && { return i; } // call to this overload is rvalue
int& get() & { return i; } // call to this overload is lvalue
};
二次
试图将rvalue作为lvalue转发,例如通过使用lvalue引用类型T实例化表单%282%29,是编译时错误。
注记
见模板参数推导关于转发引用背后的特殊规则,%28T&&
用作函数参数%29和转发引用其他细节。
参数
t | - | the object to be forwarded |
---|
返回值
static_cast<T&&>(t)...
例外
noexcept
规格:
noexcept
例
此示例演示参数%28s%29完全转发给类的构造函数的参数。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
}
二次
产出:
二次
rvalue overload, n=2
lvalue overload, n=1
B
rvalue overload, n=2
lvalue overload, n=1
rvalue overload, n=3
二次
复杂性
常量。
另见
move (C++11) | obtains an rvalue reference (function template) |
---|---|
move_if_noexcept (C++11) | obtains an rvalue reference if the move constructor does not throw (function template) |
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。