我正在尝试完美转发,发现
std::forward()需要两个重载:
过载 1:
template <typename T>
inline T&& forward(typename
std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
Run Code Online (Sandbox Code Playgroud)
重载nr.2:
template <typename T>
inline T&& forward(typename
std::remove_reference<T>::type&& t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value,
"Can not forward an rvalue as an lvalue.");
return static_cast<T&&>(t);
}
Run Code Online (Sandbox Code Playgroud)
现在,完美转发的典型场景是
template <typename T>
void wrapper(T&& e)
{
wrapped(forward<T>(e));
}
Run Code Online (Sandbox Code Playgroud)
当然,您知道何时wrapper()实例化T取决于传递给它的参数是左值还是右值。如果它是type的左值U,T则推导为U&。如果是右值,T则推导为U。
无论如何-在-的范围内wrapper()- e是一个左值,因此它始终使用的第一个重载std::forward()。
现在我的问题是:
使用(需要)第二重载的有效方案是什么?
考虑:
void g(int&);
void g(int&&);
template<class T>
void f(T&& x)
{
g(std::forward<T>(x));
}
int main()
{
f(10);
}
Run Code Online (Sandbox Code Playgroud)
由于id-expression x是一个左值,并且std::forward对于左值和右值有重载,为什么调用不能绑定到std::forward需要左值的重载?
template<class T>
constexpr T&& forward(std::remove_reference_t<T>& t) noexcept;
Run Code Online (Sandbox Code Playgroud) 简单的问题,为什么不做以下工作(暗示副本ci)?
#include <utility>
int main(){
const int ci = 2;
std::forward<int>(ci);
}
Run Code Online (Sandbox Code Playgroud)
prog.cpp:在函数'int main()'中:
prog.cpp:6:23:错误:没有用于调用'forward(const int&)'的匹配函数
在编写一些模板内容时,问题就出现了,我有一个简单的持有者类型,如下所示.为了避免不必要的副本,我尽可能使用完美转发,但结果证明它似乎是问题的根源.
template<class T>
struct holder{
T value;
holder(T&& val)
: value(std::forward<T>(val))
{}
};
template<class T>
holder<T> hold(T&& val){
// T will be deduced as int, because literal `5` is a prvalue
// which can be bound to `int&&`
return holder<T>(std::forward<T>(val));
}
template<class T>
void foo(holder<T> const& h)
{
std::tuple<T> t; // contrived, actual function takes more parameters
std::get<0>(t) = std::forward<T>(h.value); …Run Code Online (Sandbox Code Playgroud) 如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;
Run Code Online (Sandbox Code Playgroud)
典型的用法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));
}
Run Code Online (Sandbox Code Playgroud)
当我们打电话时fwd(0),T推断为int(t有类型int &&).然后我们打电话std::forward<int>(t).该调用的结果是类型的表达式,int &&因此选择了第二个overloaded函数版本,程序将"rvalue"打印到标准输出.
当我们调用fwd(i)(其中我是一些int变量)时,T推导为int&(t有类型 …