2015-04-23 16 views
5

Fill<T, Pack, Size, Value> deve essere il tipo Pack<Value, Value, ..., Value>, dove viene ripetuto il valore. Qualcuno può spiegare, perché questo è ambiguo?Qualcuno spiega perché l'ambiguità qui, per favore?

template <typename T, template <T...> class Pack, int Size, int Count, typename Output, T Value> 
struct FillHelper; 

template <typename T, template <T...> class P, int Size, int Count, T... Output, T Value> 
struct FillHelper<T, P, Size, Count, P<Output...>, Value> : 
    FillHelper<T, P, Size, Count + 1, P<Output..., Value>, Value> {}; 

template <typename T, template <T...> class P, int Size, T... Output, T Value> 
struct FillHelper<T, P, Size, Size, P<Output...>, Value> { 
    using type = P<Output...>; 
}; 

template <typename T, template <T...> class P, int Size, T Value> 
using Fill = typename FillHelper<T, P, Size, 0, P<>, Value>::type; 

template <int...> struct Pack; 

int main() { 
    using T = Fill<int, Pack, 10, 4>; 
} 

mentre questo non è:

template <typename T, int Size, int Count, typename Output, T Value> 
struct FillHelper; 

template <typename T, template <T...> class P, int Size, int Count, T... Output, T Value> 
struct FillHelper<T, Size, Count, P<Output...>, Value> : 
    FillHelper<T, Size, Count + 1, P<Output..., Value>, Value> {}; 

template <typename T, template <T...> class P, int Size, T... Output, T Value> 
struct FillHelper<T, Size, Size, P<Output...>, Value> { 
    using type = P<Output...>; 
}; 

template <typename T, template <T...> class P, int Size, T Value> 
using Fill = typename FillHelper<T, Size, 0, P<>, Value>::type; 

template <int...> struct Pack; 

int main() { 
    using T = Fill<int, Pack, 10, 4>; 
} 

Si scopre che ho indirettamente notato che il secondo è più breve e quindi migliore del primo, ma ero perplesso perché il primo non sarebbe la compilazione. Ottengo un errore con GCC 4.9.2, che è molto recente. Errore anche con Visual Studio 2013. A proposito, una soluzione migliore del secondo codice è benvenuta.

Aggiornamento: Ridurre ulteriormente il problema, si scopre che la presenza del modello-modello nelle specializzazioni non è il problema, perché questo non compilare con GCC 4.9.2 (e Visual Studio 2013 troppo):

template <typename T, template <T...> class Pack, int Size, int Count> 
struct F; 

template <typename T, template <T...> class P, int Size, int Count> 
struct F : F<T, P, Size, Count + 1> {}; 

template <typename T, template <T...> class P, int Size> 
struct F<T, P, Size, Size> { 
    using type = int; 
}; 

template <int...> struct Pack; 

int main() { 
    using T = F<int, Pack, 10, 0>::type; 
} 

Quindi, qual è esattamente il problema nel primo codice che causa confusione con GCC e VS?

+0

FWIW, clang 3.6 munches giù il primo senza errori. Info: Apple LLVM versione 6.1.0 (clang-602.0.49) (basato su LLVM 3.6.0svn). Forse includi le tue informazioni su toolchain. – WhozCraig

+0

Ottengo un errore con GCC 4.9.2, che è molto recente. Errore anche con Visual Studio 2013. – prestokeys

+0

Beh, il clang è apparentemente più intelligente di quello che siamo, in quanto realizza che di questo non è in realtà * usato *. Aggiungere 'T t;' a 'main()' fornisce una dose di: main.cpp: 23: 7: Istanza implicita del template non definito 'Pack <4, 4, 4, 4, 4, 4, 4 , 4> '. Anche se potrebbe essere utile saperlo a prescindere. ** modifica ** nm. aggiungendo '{};' dopo 'Pack' e compila ancora una volta. – WhozCraig

risposta

1

non so il motivo per cui gcc rifiuta il codice, ma se si dispone di C++ 14 di supporto, una soluzione meno noioso è quello di utilizzare std::make_index_sequence per costruire un pacchetto con Size elementi, quindi dedurre la confezione ed espandere di nuovo, in questo modo:

template <typename T, template <T...> class Pack, T Value, size_t... indices> 
auto FillHelper(std::index_sequence<indices...>) -> Pack<(indices, Value)...>; 

template <typename T, template <T...> class P, int Size, T Value> 
using Fill = decltype(FillHelper<T, P, Value>(std::make_index_sequence<Size>())); 

link: http://coliru.stacked-crooked.com/a/7771560a1f32461d

+0

Bello! Non ho mai pensato di usare l'operatore virgola. Dato che qui è solo un operatore fittizio, suppongo che qualsiasi indice_sequenza di lunghezza 'Size' possa funzionare. – prestokeys

Problemi correlati