Variadische Template-Argumente verodern.
-
camper schrieb:
Hier eine nicht-rekursive Variante
template<class... Rest> struct Or { template<typename IteratorType> static bool match(IteratorType begin, IteratorType end, IteratorType& newBegin) { bool result = false; const bool matched[] = { result = result || Rest::match(begin, end, newBegin)...}; return (void)matched, result; } };
Uh. Wie funktioniert das? Die pack expansion erstreckt sich "einfach so" auf den kompletten Ausdruck inklusive Veroderung? Oder fehlen da noch Klammern?
{ (result = result || Rest::match(begin, end, newBegin))...}
Und wozu beim return nochmal matched anführen? - damit irgendwas instantiiert wird?
-
pumuckl schrieb:
camper schrieb:
Hier eine nicht-rekursive Variante
template<class... Rest> struct Or { template<typename IteratorType> static bool match(IteratorType begin, IteratorType end, IteratorType& newBegin) { bool result = false; const bool matched[] = { result = result || Rest::match(begin, end, newBegin)...}; return (void)matched, result; } };
Uh. Wie funktioniert das? Die pack expansion erstreckt sich "einfach so" auf den kompletten Ausdruck inklusive Veroderung? Oder fehlen da noch Klammern?
Klammern wären fürs Lesen besser, habe ich nur versehentlich vergessen. Erforderlich sind sie allerdings nicht.
Es gibt keine Packexpansion für Ausdrücke per se (wenn es sie gäbe, bräuchten wir das Array ja nicht). Die relevante Expansion hier istn3337 schrieb:
initializer-list:
initializer-clause ...opt
initializer-list , initializer-clause ...optpumuckl schrieb:
{ (result = result || Rest::match(begin, end, newBegin))...}
Und wozu beim return nochmal matched anführen? - damit irgendwas instantiiert wird?
Nur um eine Warnung wegen nicht verwendeter lokaler Variablen loszuwerden.
-
camper schrieb:
Es gibt keine Packexpansion für Ausdrücke per se (wenn es sie gäbe, bräuchten wir das Array ja nicht). Die relevante Expansion hier ist
n3337 schrieb:
initializer-list:
initializer-clause ...opt
initializer-list , initializer-clause ...optAlles klar, note to myself: pack expansion nochmal genauer ansehen
-
@Camper: Aber ruft der Ausdruck dann nicht match() für alle Template-Argumente auf?
-
Ethon schrieb:
@Camper: Aber ruft der Ausdruck dann nicht match() für alle Template-Argumente auf?
Sofern match fehlschlägt, sicher?
pumuckls Version hat das Problem, das keine Kurzschlussauswertung erfolgt.
-
Ethon schrieb:
@Camper: Aber ruft der Ausdruck dann nicht match() für alle Template-Argumente auf?
Ich hab mich auch gefragt, was da pssiert, und es wie folgt getestet:
#include <iostream> using namespace std; template<class... Rest> struct Or { template<typename IteratorType> static bool match(IteratorType begin, IteratorType end, IteratorType& newBegin) { bool result = false; cout << "or::match - "; const bool matched[] = { result = result || Rest::match(begin, end, newBegin)...}; return (void)matched, result; } }; struct T { static bool match(char*, char*, char*&) {cout << "T::match - "; return true;} }; struct F { static bool match(char*, char*, char*&) {cout << "F::match - "; return false;} }; int main() { char hw[] = "Hello, World!"; char* const e = hw + sizeof(hw); char* ptr = 0; typedef Or<F,F,T> OT1; cout << OT1::match(hw, e, ptr) << '\n'; typedef Or<F,T,F> OT2; cout << OT2::match(hw,e,ptr) << '\n'; typedef Or<T,F,OT1> OT3; cout << OT3::match(hw,e,ptr) << '\n'; }
Output:
or::match - F::match - F::match - T::match - 1 or::match - F::match - T::match - 1 or::match - T::match - 1
Heißt, die späteren matches werden nicht mehr aufgerufen.
Was da nach packexpansion quasi steht ist ja auch folgendes (bei Or<F,T,F>)const bool matched[] = { result = result || F::match(begin, end, newBegin), result = result || T::match(begin, end, newBegin), result = result || F::match(begin, end, newBegin)};
Nach Auswertung einzelner matches heißt das eben
const bool matched[] = { result = false || false, result = false || true, result = true || <never mind...>};