2016-05-20 11 views
10

Die Standardalgorithmen min und max können mit einem einzelnen Wert verglichen werden. Allerdings kann der minmax Algorithmus Rückgabewert nicht gegen ein Paar von Werten verglichen werden:Vergleichen von std :: minmax mit einem Paar

#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

Der Grund dafür ist, dass make_pair(2, 1) gibt ein pair<int, int> und minmax(1, 2) kehrt ein pair<const int&, const int&>. Es gibt keine operator== Überlastungsreferenzwerte für pair.

Das Update ist dann explizit zu schreiben std::pair<const int&, const int&>(int, int) oder um diese in eine selbstgemachte make_cref_pair Funktion zu wickeln.

Fragen: Gibt es eine saubere Art und Weise den minmax Rückgabewert gegen ein pair von Werten zu vergleichen? Und habe ich die Referenzen in meiner make_cref_pair korrekt behandelt?

+1

Ich befürchte, dass 'make_cref_pair' nicht legal sein kann (Lebenszeitverlängerung nicht auf Unterobjekte gilt, AFAIK) – sehe

+0

@sehe yikes. Gilt das gleiche für das nackte 'Paar (1,2)'? – TemplateRex

+0

Es wäre das gleiche. Ich bin mir da nicht wirklich sicher, aber es scheint so, als würde man dort am Rande spielen. – sehe

Antwort

11

std::minmax hat eine initializer_list Überlastung. Dies gibt ein non-const Nicht-Referenzpaar:

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

Leider kann dies weniger performant, da jeweils die Komplexität ist „genau ein Vergleich“ und „höchstens (3/2) * t.size() Anwendungen des entsprechenden Prädikats“.

+0

Nun, ich werde nur den Vergleich zur Kompilierzeit verwenden (es ist für die Initialisierung einer Variablenvorlage, daher das C++ 14-Tag, ich brauche das 'constexpr'). Danke, das ist eine nette Antwort! – TemplateRex

+0

kennen Sie vielleicht auch die Antwort auf die Lebensdauerprobleme mit einem 'Paar '? – TemplateRex

+2

@TemplateRex Das Problem mit dangelnden Referenzen ist nur ein Problem, wenn Sie danach versuchen, auf "first" oder "second" zuzugreifen. AFAIK das ist ein Problem mit 'minmax' auch. Eine plausible Abhilfe ist die Verwendung von 'reference_wrapper'. – user6362820

5

Eine Sache, die Sie tun könnten, ist die Überlastung std::minmax, die eine std::initializer_list<T> dauert und eine std::pair<T,T> zurückgibt. Mit, dass Sie

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)); 
} 

Welche will compile haben könnte und ermöglicht es Ihnen, von make_cref_pair loszuwerden. Es ruft std::minmax_element an, also bin ich nicht sicher, ob dies die Effizienz verringert oder nicht.

3

Eine Möglichkeit besteht darin, explizit auf der linken Seite zu std::pair<int,int> konvertieren:

#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

die Initialisierungsliste-Klammern sind eine bequemere Möglichkeit, dies zu erreichen – TemplateRex

+0

Welche Variante für Sie am besten funktioniert. Das liegt an dir :) – mindriot

Verwandte Themen