2016-05-20 17 views
10

標準アルゴリズムminmaxは、単一の値と比較することができます。しかし、minmaxアルゴリズムの戻り値は、値の組と比較することができない。std :: 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<int, int>minmax(1, 2)pair<const int&, const int&>を返すことです。参照先はありません。pairの場合は、operator==のオーバーロードが混在しています。

この修正は、std::pair<const int&, const int&>(int, int)を明示的に書き込むか、またはこれを自家製のmake_cref_pair関数でラップすることです。

質問:値のpairに対するminmax戻り値を比較するためのクリーンな方法は何ですか?そして私はmake_cref_pairの参照を正しく処理しましたか?

+1

私は 'make_cref_pair'は合法ではないかもしれないことを恐れる(寿命延長が私の知る限り、サブオブジェクトには適用されません) – sehe

+0

@セクシーな男。同じことが、裸の 'pair (1,2)'にも適用されますか? – TemplateRex

+0

それは同じでしょう。私はこれについて本当に確信していませんが、それは端に遊んでいるように思えます – sehe

答えて

11

std::minmaxは、オーバーロードがinitializer_listです。これはnon-const非基準ペアを返す:

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

複雑さは、それぞれ、「正確に一つの比較」と「対応する述語のせいぜい(3/2) * t.size()アプリケーション」であるので、残念ながら、これは、より少ないパフォーマンスであってもよいです。

+0

私はコンパイル時にのみ比較を使用します(変数テンプレートを初期化するため、C++ 14タグ、 'constexpr'が必要です)。ありがとう、これはいい答えです! – TemplateRex

+0

あなたはおそらく 'pair 'を使って生涯の問題に対する答えを知っていますか? – TemplateRex

+2

@TemplateRex参照をぶら下げる問題は、後で 'first'または' second'にアクセスしようとすると問題になります。 AFAIKこれも 'minmax'の問題です。考えられる回避策は 'reference_wrapper'を使うことです。 – user6362820

5

あなたができることの1つは、std::minmaxオーバーロードを利用して、std::initializer_list<T>を受け取り、std::pair<T,T>を返すことです。あなたは

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<int,int>に左側を変換することです:

#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)); 
} 
+0

イニシャライザリストの中括弧は、これを実現するためのより便利な方法です – TemplateRex

+0

あなたのために最適などちらの方法が適していますか?それはあなた次第です :) – mindriot

関連する問題