【问题标题】:Comparing std::minmax against a pair将 std::minmax 与一对进行比较
【发布时间】:2016-09-18 04:47:31
【问题描述】:

标准算法minmax 可以与单个值进行比较。但是,minmax 算法的返回值无法与一对值进行比较:

#include <algorithm>
#include <utility>

template<class T1, class T2>
constexpr auto make_cref_pair(T1&& t1, T2&& t2)
{
    return std::pair<T1 const&, T2 const&>(std::forward<T1>(t1), std::forward<T2>(t2));
}

int main()
{
    static_assert(std::min(2, 1) == 1); // OK
    static_assert(std::max(2, 1) == 2); // OK
    //static_assert(std::minmax(2, 1) == std::make_pair(1, 2)); // ERROR, const int& vs int pair comparison
    static_assert(std::minmax(2, 1) == std::pair<const int&, const int&>(1, 2)); // OK
    static_assert(std::minmax(2, 1) == make_cref_pair(1, 2)); // OK
}

Live Example

原因是make_pair(2, 1) 返回一个pair&lt;int, int&gt;minmax(1, 2) 返回一个pair&lt;const int&amp;, const int&amp;&gt;pair 没有引用混合 operator== 重载。

然后解决方法是显式编写 std::pair&lt;const int&amp;, const int&amp;&gt;(int, int) 或将其包装在自制的 make_cref_pair 函数中。

问题:有没有更简洁的方法来比较 minmax 返回值和 pair 的值?我是否正确处理了make_cref_pair 中的引用?

【问题讨论】:

  • 我担心make_cref_pair 可能不合法(延长寿命不适用于子对象,AFAIK)
  • @sehe 哎呀。这同样适用于裸pair&lt;int const&amp;, int const&amp;&gt;(1,2)吗?
  • 应该是一样的。我不太确定这一点,但它看起来确实像在边缘玩
  • 也许另一种方法是自己提供适当的operator== 重载。在对象生命方面,它可能比cref_pair 更安全,但另一方面它引入了“意外”的过载。
  • @sehe 看起来并不比forward_as_tuple 更危险。

标签: c++ algorithm c++14 minmax


【解决方案1】:

std::minmax 有一个initializer_list 过载。这将返回一个 non-const 非引用对:

static_assert(std::minmax({2, 1}) == std::make_pair(1, 2));

不幸的是,这可能会降低性能,因为复杂性分别是“恰好一个比较”和“最多(3/2) * t.size() 相应谓词的应用程序”。

【讨论】:

  • 好吧,我只会在编译时使用比较(它用于初始化变量模板,因此 C++14 标记,我需要constexpr)。谢谢,这是一个很好的答案!
  • 您是否也知道使用pair&lt;int const&amp;, int const&amp;&gt; 解决生命周期问题的答案?
  • @TemplateRex 只有在之后尝试访问firstsecond 时,才会出现悬空引用的问题。 AFAIK 这也是minmax 的问题。一个可行的解决方法是使用reference_wrapper
【解决方案2】:

您可以做的一件事是利用std::minmax 重载,它接受std::initializer_list&lt;T&gt; 并返回std::pair&lt;T,T&gt;。使用它你可以拥有

int main()
{
    const int a = 10, b = 20;
    static_assert(std::minmax({2, 1}) == std::make_pair(1, 2));
    static_assert(std::minmax({a, b}) == std::make_pair(a, b));
}

其中will compile 并允许您摆脱make_cref_pair。它确实调用了std::minmax_element,所以我不确定这是否会降低效率。

【讨论】:

    【解决方案3】:

    一种选择是将左侧显式转换为std::pair&lt;int,int&gt;

    #include <algorithm>
    #include <utility>
    
    template <typename T1, typename T2>
    constexpr std::pair<T1,T2> myminmax(const T1& t1, const T2& t2)
    {
        return std::minmax(t1,t2);
    }
    
    int main()
    {
        static_assert(myminmax(2, 1) == std::make_pair(1, 2));
    }
    

    【讨论】:

    • 初始化列表大括号是实现此目的的更方便的方法
    • 哪种变体最适合您。这取决于你:)
    猜你喜欢
    • 2017-04-09
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 2022-09-30
    • 2019-01-17
    • 1970-01-01
    相关资源
    最近更新 更多