最小化算法通常表达为:
template <typename T>
const T& min(const T& x, const T& y)
{
return y < x ? y : x;
}
然而,这并不允许形如
min(a, b) = 0
的构造。您可以通过添加额外的重载来实现:template <typename T>
T& min(T& x, T& y)
{
return y < x ? y : x;
}
我想通过完美转发将这两种重载统一起来:
template <typename T>
T&& min(T&& x, T&& y)
{
return y < x ? std::forward<T>(y) : std::forward<T>(x);
}
然而,g++ 4.5.0对于
min(2, 4)
会发出警告,指出我返回了一个临时对象的引用。我做错了什么吗?
好的,我明白了。问题出在条件运算符上。在我的第一种解决方案中,如果我调用
min(2, 4)
,条件运算符会看到一个xvalue,因此从转发的x
移动以产生临时对象。当然,返回该对象的引用是危险的!如果我转发整个表达式而不是分别转发x
和y
,编译器就不会再抱怨了:template <typename T>
T&& min(T&& x, T&& y)
{
return std::forward<T>(y < x ? y : x);
}
好的,我已经删除了算术类型的引用 :)
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type
min(T x, T y)
{
return y < x ? y : x;
}
template <typename T>
typename std::enable_if<!std::is_arithmetic<T>::value, T&&>::type
min(T&& x, T&& y)
{
return std::forward<T>(y < x ? y : x);
}
int&&
绑定到int
xvalue而创建临时变量?我认为xvalues是匿名rvalue引用,可以通过rvalue引用绑定而不必创建临时变量?您的修改后的代码似乎也是如此。返回类型是int&&
,返回表达式是int
xvalue。为什么编译器不再发出警告呢? - Johannes Schaub - litbint
不是一个类类型。因此,对于int
,会创建一个临时变量。我认为这是一个缺陷。 - Johannes Schaub - litb