模板接受const但不接受文字

时间:2018-08-29 11:44:53

标签: c++ templates generic-programming

编写模板时,class T可以用const类型代替。

考虑:

template<class T> T& min(T& a, T& b) {
    return a < b ? a : b;
}

在以下情况下这将起作用:

int a = 1, b = 5;
const int c = 1, d = 5;
min(a, b); // T is int
min(c, d); // T is const int

但是在使用文字调用时会引发编译错误(像这样):

min(1, 5); // T is const int literal
  

从“ int”类型的右值无效初始化“ int&”类型的非常量引用

为什么? int文字不是const int吗?以及如何修改模板以允许使用文字?

(与gcc 6.3和MSVC 2015一致)

3 个答案:

答案 0 :(得分:3)

int文字的类型为int,而不是const int。因此,T被推导为intcmd terminal working fine

编写这样一个函数的正确方法是完善自变量,或者使用const T&,两者都可以绑定到任何东西。

template<typename T, typename U>
auto min(T&& a, U&& b) -> decltype(a < b ? std::forward<T>(a) : std::forward<U>(b))
{
    return a < b ? std::forward<T>(a) : std::forward<U>(b); 
}

// Or...
template<typename T>
const T& min(const T& a, const T& b)
{
    return a < b ? a : b;
}

在完美传递参数的情况下,需要两个模板参数才能编译int a{}; min(a, 42);,因为它们的推导类型不同。

答案 1 :(得分:2)

  

int文字不是const int吗?

否,它只是int,而不是constis defined as a prvalue,因此左值引用不能与其绑定-就像您的情况。

通过使用如下原始模板即可轻松进行纠正:

template<typename T>
const T& min(const T& a, const T& b){
    return a < b ? a : b;
}

const T&一样也会绑定到 rvalue s。

避免更改或添加类似内容:

template<typename T, typename U>
auto&& min(T&& a, U&& b){
    return std::forward<T>(a < b ? a : b); 
}

在这里,我们不会从物化临时目录中创建副本,因此,存在返回悬挂参考的风险。在[class.temporary]中查看此处:

  

绑定到函数调用中的参考参数的临时对象   ([expr.call])一直持续到完整表达式完成   包含呼叫。

...它死了。因此悬空。

答案 2 :(得分:0)

Literal产生T&无法接受的prvalue表达式。 T&仅接受左值。

您可以这样考虑:整数立即数是“无生命的”事物,因为它在任何地方都没有地址,如何将其绑定到左值引用然后进行修改?该物体将位于何处?更改将写入何处?