2016-05-21 14 views
15

Nach N4295 C++ 17 wird mir erlauben, die Summe von einer unbekannten Anzahl von Argumenten so zu berechnen:Folding Ausdrücke in C++ 17 - Usecase für Vergleichsoperatoren

template<typename ... T> 
int sum(T...t) 
{ 
    return (... + t); 
} 

Das Dokument heißt es ferner, ich könnte Operatoren wie == oder> anstelle von + verwenden. Kann jemand ein vernünftiges Beispiel dafür finden, wann ich == oder> in solch einem Konstrukt verwenden möchte?

(Ich weiß, dass die Menschen == und definieren> seltsame Dinge zu fremden Klassen zu tun, aber sicher, dass gegen gute Praxis. Schreiben a > b > c > d ist so gut wie nie eine gute Idee, oder?)

+0

Wenn Sie eine binäre Faltung mit einem speziellen Startelement verwenden, könnten Sie vielleicht '(apply_op() == ... == t)' sagen, um den Operator 'apply_op' zu machen ==' machen Sie das Recht Ding? –

+0

Soweit ich mich erinnere, wurden unäre Falten für + entfernt. Sie müßten schreiben '(T {} + ... + t)' oder '(t + ... + T {})' (oder welcher Wert auch immer für Sie Sinn macht). – chris

+0

@chris Sie wurden nur entfernt, wenn das Parameterpaket leer ist. Solange mindestens ein Element in "... t" ist, funktioniert die obige Funktion immer noch wie erwartet. – Morwenn

Antwort

10

Ich wäre ein interessantes Feature, wenn verkettete Vergleiche wie in Python behandelt werden, wobei a < b < c als a < b and b < c mit einer einzigen Auswertung von b interpretiert wird. Leider ist dies in C++ nicht der Fall und selbst in seltsamen Fällen ergeben faltbare Vergleichsoperatoren tatsächlich kaum Sinn.

Beachten Sie, dass es a proposal (P0313) wurde durch fold Ausdrücke gänzlich behandelt die Operatoren ==, !=, <, >, <= und >= von den Betreibern, um tatsächlich zu entfernen. Es wurde während der Ausschusssitzung im Juni 2016 in Oulu diskutiert. Die Motivation für die Entfernung war eher kurz:

Vergleichsoperatoren machen nicht viel Sinn in Fold-Ausdrücke; Sie erweitern sich zu Ausdrücken, die überraschende Effekte haben, und sind daher nur für dsl-Metaprogrammer nützlich. [...] Es wäre schön, Ausdrücke wie a < b < c fixieren zu können. Das würde eine Zeitmaschine erfordern. Das Problem für Fold-Expressions nicht zu wiederholen scheint machbar.

Das sagte der Vorschlag wurde abgelehnt.

+1

Man kann solche Operatoren überfordern, sich unterschiedlich zu verhalten, wo das Falten zu einer netten Funktion führen würde. Vielleicht;) – Zereges

+2

Ich würde eine "Mix-Faltung" bevorzugen, wo Sie "t op1 ... op2" für unäre Falten und "t op1 ... op2 e" für binäre Falten sagen können, die sich zu "t1 op1 t2 op2 t2 op1" erweitert t3 ... ". –

+0

@ JohannesSchaub-litb Zeit um einen weiteren Vorschlag zu schreiben? : p – Morwenn

0

Auf Anwendungsfall wäre expression templates, für die die Vergleichsoperatoren (z. B. operator ==) ein Klassenobjekt statt bool zurückgeben.

Ich auch zu kämpfen, um ein nützliches Beispiel auch hier zu kommen.

0

Dies ist keine "direkte Faltung von == allein", sondern ein "& & gefaltet mit einem Ausdruck mit ==". Aber das ist die Lösung, die ich verwende, um Werte zu vergleichen, und vielleicht ist dies auch die Art von Anwendung, die Sie im Sinn hatten.

Dies funktioniert für mich, für beide g ++ und Klirren ++

template <typename TYPE, typename... TYPE_TAIL> 
constexpr bool same_value([[maybe_unused]] TYPE value, TYPE_TAIL... value_tail) 
{ 
    return (... && (value == value_tail)); 
} 

static_assert(same_value(3)); 
static_assert(same_value(3, 3)); 
static_assert(!same_value(3, 1)); 
static_assert(same_value(3, 3, 3)); 
static_assert(!same_value(3, 1, 3)); 

int main() {} 

Compilation:

clang++ -std=c++1z testFold.cpp -o testFold 

(Version: Klirren Version 5.0.0- + rc2-1 (Tags/RELEASE_500/RC2)

)

oder

g++ -std=c++17 testFold.cpp -o testFold 

(Version: g ++ (Debian 7.2.0-8) 7.2.0)

Die [[maybe_unused]] verhindert Compiler zu warnen, wenn same_value(one_arg) mit nur einem Argumente, wie in diesem Fall die Funktion gibt den neutralen Wert für den & & Operator (das ist true genannt wird).