带有模板化重载函数的std :: forward

时间:2016-04-27 20:24:59

标签: templates c++11 move-semantics

我不知道为什么编译器会给我关于模板实例化的警告。

这是一段运行得很好的代码并正确输出lvalue / rvalue:

//template<typename T>
void overloaded(const /*T*/std::string& in)
{
    std::cout << "lvalue" << std::endl;
}

//template<typename T>
void overloaded(/*T*/std::string&& in)
{
    std::cout << "rvalue" << std::endl;
}

template<typename T>
void pass(T&& in)
{
    overloaded(std::forward<T>(in));
}

int main()
{
    std::string a;
    pass(a);
    pass(std::move(a));
    getchar();
}

但我需要使用模板类型。所以将“重载”函数修改为

template<typename T>
void overloaded(const T& in)
{
    std::cout << "lvalue" << std::endl;
}

template<typename T>
void overloaded(T&& in)
{
    std::cout << "rvalue" << std::endl;
}

给出模板实例化警告,(对我来说,它的明确T应该是std :: string),控制台输出rvalue 2次而不是lvalue。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

T&&等模板很特别。他们被称为&#34;转发参考&#34;。他们对以下功能有特殊的扣除规则:

template<typename T>
void overloaded(T&& in)

假设overloaded没有超载。如果将std::string类型的左值表达式传递给overloadedT将推导为std::string&。如果您将std::string类型的右值表达式传递给overloadedT将推导为std::string。您可以使用此知识来执行此操作:

template<typename T>
void overloaded(T&& in)
{
    if (std::is_lvalue_reference<T>::value)
        std::cout << "lvalue" << std::endl;
    else
        std::cout << "rvalue" << std::endl;
}

通常,使用其他任何内容来重载T&&模板是一种反模式。当你想抓住所有东西时,这些特殊模板会派上用场。