分钟和完美的转发
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,现在是时候这样做了。 右值引用不断发展,所以它的最小值和最大值的引用实现可能不再正确,但它至少应该是一个相当不错的起点。 警告:参考实现比您想要的复杂得多!
你不想要完美的转发,在这里,你想要返回T&
或者const T&
并且从不T&&
。 std::forward
用于将你的一个参数传递给另一个函数,而不是返回值。
我想你想要的是:
template <typename T>
min(T&& x, T&& y) -> decltype(x)
{
return y < x ? y : x;
}
编辑避免悬而未决的参考问题:
template <typename T>
struct dedangle { typedef T type; }
template <typename T>
struct dedangle<const T&> { typedef T type; }
template <typename T, typename U>
min(T&& x, U&& y) -> dedangle<decltype(0?y:x)>::type
{
return y < x ? y : x;
}
// dedangle is re-usable by max, etc, so its cost is amortized
链接地址: http://www.djcxy.com/p/46385.html
上一篇: min and perfect forwarding
下一篇: what audio formats are supported by the android browser?