2014-05-13 3 views
7

Betrachten Ich habe eine variadic Vorlage mit int... Parameter. Zum Beispiel eine Funktion wie diese:Alle Parameter mit Erweiterung des Parameterpakets hinzufügen

template<int... t> 
int add(){ 
    return t... + ??? 
} 

Alle Methode sollten alle Parameter hinzufügen. Es kann leicht mit rekursiven Variadischen Vorlagen erreicht werden. Ist es jedoch auch möglich, dies (oder etwas Ähnliches wie die Verwendung anderer binärer Operatoren zum Aggregieren aller Template-Parameter) unter Verwendung der Parameter-Pack-Erweiterung auszudrücken?

+0

Nein. Tun Sie es einfach so, wie es leicht erreicht werden kann. –

+0

Okay, ich dachte nur, es könnte noch einfacher und besser verständlich mit Parameter-Erweiterung sein :) – gexicide

+2

Das Problem mit den anderen Lösungen ist, berechnen sie die Zugabe in der Ausführungszeit. –

Antwort

18

Ja, mit einem Trick lernte ich @Xeo in der Lounge. Ich habe es ursprünglich verwendet, um eine variable "Druck" -Schablonenfunktion zu erstellen.

#include <iostream> 

template<int... ints> 
int add() 
{ 
    int result = 0; 
    using expand_variadic_pack = int[]; // dirty trick, see below 
    (void)expand_variadic_pack{0, ((result += ints), void(), 0)... }; 
    // first void: silence variable unused warning 
    // uses braced-init-list initialization rules, which evaluates 
    // the elements inside a braced-init-list IN ORDER, to repetetively 
    // execute a certain operation 
    // second void is to prevent malicious "operator," overloads, which 
    // cannot exist for void types 
    // 0 at the end is to handle empty variadic pack (zero-size array initializer is illegal. 
    return result; 
} 

int main() 
{ 
    std::cout << add<1,2,3,4>() << '\n'; 
} 

Dies funktioniert auf jedem Compiler, die menschenwürdige C++ 11-Unterstützung (GCC 4.8+, Clang 3.2+, MSVS2013, ...) hat

+8

Nicht sicher, ob zu lachen oder zu weinen –

+0

@Lightness sicherlich haben Sie Nebenwirkungen von Ausdrücken zuvor in C++ missbraucht. – rubenvb

+0

Natürlich! –

6

Eine mögliche Variante, das Lambda und std::accumulate verwendet:

#include <array> 
#include <numeric> 

template <int... t> 
int add() 
{ 
    return [](const std::array<int, sizeof...(t)>& a) 
    { 
     return std::accumulate(a.begin(), a.end(), 0); 
    }({t...}); 
} 
+1

Dieser sieht sauber aus und viel weniger von einem Hack! Leider ist es unwahrscheinlich, dass Berechnungen in der Kompilierzeit optimiert werden. –