min 算法通常表示如下:
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);
}
最佳答案
在我看来,您似乎在试图过分简化问题。不幸的是,让它完全正确绝对不是一件容易的事。如果你还没有读过 N2199 ,现在是这样做的好时机。右值引用不断发展,因此它的 min 和 max 引用实现可能不再完全正确,但它至少应该是一个相当不错的起点。警告:引用实现比您想要的要复杂很多!
关于c++ - 最小和完美转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3095549/