为什么使用std :: forward禁用模板参数扣除? [英] Why is template argument deduction disabled with std::forward?

查看:172
本文介绍了为什么使用std :: forward禁用模板参数扣除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在VS2010中,std :: forward定义如下:

In VS2010 std::forward is defined as such:

template<class _Ty> inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{   // forward _Arg, given explicitly specified type parameter
    return ((_Ty&&)_Arg);
}

出现在
仅用于禁用模板参数扣除。

identity appears to be used solely to disable template argument deduction. What's the point of purposefully disabling it in this case?

推荐答案

如果您将一个右值引用传递给一个类型<$ c的对象$ c> X 到模板函数,该函数以类型 T&& 作为其参数,模板参数扣除推导 T X 。因此,参数具有类型 X&&&。如果函数参数是一个左值或常量值,则编译器将其类型推断为该类型的左值引用或常量左值引用。

If you pass an rvalue reference to an object of type X to a template function that takes type T&& as its parameter, template argument deduction deduces T to be X. Therefore, the parameter has type X&&. If the function argument is an lvalue or const lvalue, the compiler deduces its type to be an lvalue reference or const lvalue reference of that type.

如果 std :: forward 使用模板参数扣除:

If std::forward used template argument deduction:

由于对象的名称为lvalue ,只有 std :: forward 正确地转换为 T&&& 将是输入参数是未命名的右值(如 7 func())。在完美转发的情况下,传递到 std :: forward arg 是一个左值,因为它有一个名称。 std :: forward 的类型将被推导为一个左值引用或常量值引用。参考折叠规则会导致std中的 T&&< / code> in static_cast< T&&>(arg) :: forward to always resolve as a lvalue reference or const lvalue reference。

Since objects with names are lvalues the only time std::forward would correctly cast to T&& would be when the input argument was an unnamed rvalue (like 7 or func()). In the case of perfect forwarding the arg you pass to std::forward is an lvalue because it has a name. std::forward's type would be deduced as an lvalue reference or const lvalue reference. Reference collapsing rules would cause the T&& in static_cast<T&&>(arg) in std::forward to always resolve as an lvalue reference or const lvalue reference.

示例:

template<typename T>
T&& forward_with_deduction(T&& obj)
{
    return static_cast<T&&>(obj);
}

void test(int&){}
void test(const int&){}
void test(int&&){}

template<typename T>
void perfect_forwarder(T&& obj)
{
    test(forward_with_deduction(obj));
}

int main()
{
    int x;
    const int& y(x);
    int&& z = std::move(x);

    test(forward_with_deduction(7));    //  7 is an int&&, correctly calls test(int&&)
    test(forward_with_deduction(z));    //  z is treated as an int&, calls test(int&)

    //  All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as
    //  an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int& 
    //  or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what 
    //  we want in the bottom two cases.
    perfect_forwarder(x);           
    perfect_forwarder(y);           
    perfect_forwarder(std::move(x));
    perfect_forwarder(std::move(y));
}

这篇关于为什么使用std :: forward禁用模板参数扣除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆