rvalues refs vs const lvalue refs的C ++模板参数推导

时间:2014-07-28 18:21:49

标签: c++ c++11

我有下一个代码:

#include <utility>

template<typename T>
struct fun
{
    fun(T&&){}
    fun(const T&){}
};

template<typename T>
fun<T> create_fun(T&& val)
{
    return fun<T>(std::forward<T>(val));
}

template<typename T>
fun<T> create_fun(const T& val)
{
    return fun<T>(val);
}

int main()
{
    int i = 1;
    const int ci = 2;

    fun<int> a = create_fun<int>(1);
    fun<int> b = create_fun<int>(i);
    fun<int> c = create_fun<int>(ci);

    fun<int> d = create_fun(1);
    fun<int> e = create_fun(i);
    //error: no viable conversion from fun<int&> to fun<int>
    //why is create_fun(T&& val) a better match than create_fun(const T& val)?
    fun<int> f = create_fun(ci);

    return 0;
}

你能解释一下为什么对于非常数值,通用引用是更好的匹配吗?

如果没有明确指定a的类型,我如何才能实现与bccreate_fun相同的行为?

编辑:

我想强制fun使用int作为所有3个调用的参数

生成
#include <utility>

template<typename T>
struct fun
{
    fun(T&&){}
};

template<typename T>
fun<T> create_fun(T&& val)
{
    return fun<T>(std::forward<T>(val));
}

template<typename T>
struct show_type;

int main()
{
    int i = 1;
    const int ci = 2;

    show_type<decltype(create_fun(1))>();
    show_type<decltype(create_fun(i))>();
    show_type<decltype(create_fun(ci))>();

    return 0;
}

1 个答案:

答案 0 :(得分:3)

鉴于create_fun(i);具有非常量左值i,两个竞争重载的模板参数推断导致:

fun<T> create_fun(T&& val) ==> fun<int&> create_fun(int& val)  (T = int &)
fun<T> create_fun(const T& val) ==> fun<int> create_fun(const int& val)  (T = int)

第一个是比第二个更好的匹配§13.3.3.2[over.ics.rank] /3.1.6。所以第一个被选中。

您可以只使用一个通用参考模板,而不是使用两个重载,并从const的返回类型中移除T中的引用和create_fun

template<typename T>
using remove_cv_and_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

template<typename T>
fun<remove_cv_and_ref_t<T>> create_fun(T&& val)
{
    return fun<remove_cv_and_ref_t<T>>(std::forward<T>(val));
}

Demo