编写模板时,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一致)
答案 0 :(得分:3)
int
文字的类型为int
,而不是const int
。因此,T
被推导为int
和cmd 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
,而不是const
和is 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&
仅接受左值。
您可以这样考虑:整数立即数是“无生命的”事物,因为它在任何地方都没有地址,如何将其绑定到左值引用然后进行修改?该物体将位于何处?更改将写入何处?