分钟和完美的转发

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移出以产生一个临时对象。 当然,通过参考返回是很危险的! 如果我单独转发整个表达式而不是xy ,编译器不再抱怨:

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?