Mentre faccio una programmazione di template variadic in C++ 11 su GCC, una volta ogni tanto ottengo un errore che dice "Spiacente, non implementato: impossibile espandere 'Identificatore ...' in un elenco di archi a lunghezza fissa." Se rimuovo "..." nel codice, viene visualizzato un errore diverso: "errore: pacchetti di parametri non espansi con '...'".Errore GCC con modelli variadici: "Spiacente, non implementato: impossibile espandere 'Identificatore ...' in un elenco di argomenti a lunghezza fissa"
Quindi, se ho la "..." in, GCC chiamate che un errore, e se prendo il "..." fuori, GCC chiamate che un errore troppo.
L'unico modo in cui sono riuscito a risolvere questo problema è di riscrivere completamente il metaprogramma del modello da zero utilizzando un approccio diverso e (con un po 'di fortuna) alla fine mi viene il codice che non causa l'errore. Ma mi piacerebbe davvero sapere cosa stavo facendo male. Nonostante Googling per questo e nonostante molti esperimenti, non riesco a definire cosa stia facendo in modo diverso tra il codice del modello variadic che produce questo errore e il codice che non ha l'errore.
La formulazione del messaggio di errore sembra implicare che il codice dovrebbe funzionare secondo lo standard C++ 11, ma GCC non lo supporta ancora. O forse è un bug del compilatore?
Ecco alcuni codice che genera l'errore. Nota: non si ha bisogno di scrivere una corretta implementazione per me, ma solo per sottolineare ciò che è di circa il mio codice che causa questo errore specifico
// Used as a container for a set of types.
template <typename... Types> struct TypePack
{
// Given a TypePack<T1, T2, T3> and T=T4, returns TypePack<T1, T2, T3, T4>
template <typename T>
struct Add
{
typedef TypePack<Types..., T> type;
};
};
// Takes the set (First, Others...) and, while N > 0, adds (First) to TPack.
// TPack is a TypePack containing between 0 and N-1 types.
template <int N, typename TPack, typename First, typename... Others>
struct TypePackFirstN
{
// sorry, unimplemented: cannot expand ‘Others ...’ into a fixed-length argument list
typedef typename TypePackFirstN<N-1, typename TPack::template Add<First>::type, Others...>::type type;
};
// The stop condition for TypePackFirstN: when N is 0, return the TypePack that has been built up.
template <typename TPack, typename... Others>
struct TypePackFirstN<0, TPack, Others...> //sorry, unimplemented: cannot expand ‘Others ...’ into a fixed-length argument list
{
typedef TPack type;
};
EDIT: ho notato che, mentre un modello di un'istanza parziale che sembra non subire l'errore:
template <typename... T>
struct SomeStruct<1, 2, 3, T...> {};
riscrittura come questo non produce un errore:
template <typename... T>
struct SomeStruct<1, 2, 3, TypePack<T...>> {};
Sembra che si può dichiarare parametri per specializzazioni parziali per essere variadic; cioè questa linea è OK:
template <typename... T>
Ma non si può in realtà uso quei pacchetti di parametri nella specializzazione, cioè questa parte non è OK:
SomeStruct<1, 2, 3, T...>
Il fatto che si può farlo funzionare se si avvolge il pacchetto in un altro tipo, vale a dire in questo modo:
SomeStruct<1, 2, 3, TypePack<T...>>
mi implica che la dichiarazione di del parametro variadic per una specializzazione del modello parziale ha avuto esito positivo e non è possibile utilizzarlo direttamente. Qualcuno può confermarlo?
Può funzionare ora con 'clang 3.2' – alfC