Desidero chiedere se il seguente codice è valido.Espansioni multiple di più pacchetti di parametri nella stessa espressione
Mi chiedo se sia possibile espandere i pacchetti di parametri più volte in un'unica espressione.
#include <iostream>
#include <tuple>
class ExpandWithConstructor
{
public:
template <typename ... T>
ExpandWithConstructor(T... args) { }
};
template <typename T>
int PrintArgs(T arg)
{
std::cout << arg << ", ";
return 0;
}
template <typename Head, typename ... T>
class DebugPrinter: public DebugPrinter<T...>
{
public:
DebugPrinter() { }
template< typename ...Y>
DebugPrinter(Y ... rest)
{
std::cout << "Construction of: " << __PRETTY_FUNCTION__ << " Values: " ;
ExpandWithConstructor{PrintArgs(rest)...};
std::cout << std::endl;
}
};
template <typename Head>
class DebugPrinter<Head>
{
public:
};
template <typename ... T>
class TypeContainer: public std::tuple<T...>
{
public:
TypeContainer(T... args):std::tuple<T...>(args...){};
};
template <typename... T1> class CheckVariadic;
template <typename... T1, typename ...T2>
class CheckVariadic< TypeContainer<T1...>, TypeContainer<T2...>> :
public DebugPrinter< T1, T2, T1...>...
{
public:
CheckVariadic(T1... args1, T2... args2, T1... args3): DebugPrinter< T1, T2, T1...>(args1, args2..., args1)... {}
};
int main()
{
CheckVariadic< TypeContainer<int,float>, TypeContainer<char, void*>> checkVariadic1{ 1,2.2,'c',(void*)0xddddd,5,6.6,};
}
Come si può vedere il codice utilizza: DebugPrinter < T1, T2, T1 ...> ...
se T1 è dato con "int, float" e T2 è "char, void *" che si espande
DebugPrinter< T1, T2, int, float>...
che si espande
DebugPrinter< int, char, int, float>
DebugPrinter< float, void*, int, float>
La stessa espansione va con:
DebugPrinter< T1, T2, T1...>(args1, args2..., args1)...
il codice viene compilato con clang3.3 ma NON con gcc4.8.1 quindi voglio chiedere se il codice è valido o meno.
Aggiornamento: gcc 7.2 ancora non ha compilato il codice.
posso farlo compilare in g ++ 4.7 utilizzando 'DebugPrinter {args1, args2 ..., args1} ... ', ma l'uscita è nella direzione opposta di clang. –
kennytm
L'ordine inverso delle chiamate di funzione da un elenco di inizializzazione del costruttore è un bug noto in g ++. Posso anche compilare il codice con g ++ 4.7.2. Ma g ++ 4.8.1 non riesce ancora. – Klaus
@KennyTM: per essere precisi, per le funzioni regolari l'ordine di valutazione degli argomenti non è specificato; storicamente g ++ ha usato l'ordine da destra a sinistra. Per una lista di inizializzazione, credo che l'ordine sia specificato e g ++ semplicemente non è riuscito ad aggiornarlo ancora. –