c++ - 为什么使用 std::forward 禁用模板参数推导?

标签 c++ visual-studio-2010 stl c++11

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

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

identity 似乎仅用于禁用模板参数推导。在这种情况下有意禁用它有什么意义?

最佳答案

如果将右值引用传递给 X 类型的对象到采用类型 T&& 的模板函数作为其参数,模板参数推导推导 T成为X .因此,该参数的类型为 X&& .如果函数参数是左值或 const 左值,则编译器将其类型推断为该类型的左值引用或 const 左值引用。

如果std::forward使用的模板参数推导:

objects with names are lvalues唯一一次std::forward会正确转换为 T&&当输入参数是一个未命名的右值时(如 7func() )。在完美转发的情况下arg你传递给std::forward是一个左值,因为它有一个名字。 std::forward的类型将被推断为左值引用或 const 左值引用。引用折叠规则会导致 T&&static_cast<T&&>(arg)在 std::forward 中始终解析为左值引用或 const 左值引用。

示例:

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));
}

关于c++ - 为什么使用 std::forward 禁用模板参数推导?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24936441/

相关文章:

c++ - 将函数查找与 C++ 中的模板混淆

c++ - 标题和主模板的指导 - 请寻求最佳实践

c# - 通过 COM 从 C++ 解决方案调试 C# dll

c - 使用 Visual Studio Express C++ 进行 C 编程的设置和配置?

c# - 表单在运行时可见,但在设计时不可见

c++ - 在从全局对象调用的静态库函数中使用 std::vector 时调试断言失败

c++ - std::greater 未在 MSVC2012 中定义

c++ - 类的 index_sequence 用法

c++ - 使用非英文文件名调用 avio_open 函数无效

java - 运算符重载 STL 的性能损失是什么