2017-11-29 5 views
0

Ich habe Umsetzung der Liste der ints mit Vorlage:Operationen über Liste der ints mit Metaprogrammierung [C++ 11]

template<int ... Int> 
struct IntList; 

template<int H, int ... T> 
struct IntList<H, T...>{ 
    static const int Head = H; 
    using Tail = IntList<T...>; 
}; 
template<> 
struct IntList<>{}; 

Ich möchte Metafunktionen definieren mit IntList arbeiten: IntCons, die Liste zu erhöhen erlaubt durch ein Element und Generate, die eine Liste der Länge N mit ints von 0 bis N-1 (Beispiel für die Verwendung zur Erzeugung ermöglicht.using L = Generate<5>::type; // IntList<0,1,2,3,4>) I IntCons definieren auf diese Weise:

template<int H, typename IL> 
struct IntCons; 

template<int H, int... Tail> 
struct IntCons<H, IntList<Tail...>>{ 
    using type = IntList<H, Tail...>; 
}; 

Und ich kann Metafunktion Generate auf solche Weise nicht definieren, dass Funktion IntCons innerhalb verwenden. Hier ist Hinweis, ich brauche Standardparameter in Generate verwenden.

Wie definieren Sie die Meta-Funktion Generate, wie kann ich sie implementieren?

+0

Was haben Sie versucht? Was funktioniert nicht? – Barry

+0

@Barry Ich verstehe nicht, was ich tun muss, also habe ich nicht so viel versucht. – user1786089

Antwort

1

Ihr Generate ist sehr ähnlich zu std::make_index_sequence; Vielleicht können Sie eine Implementierung suchen.

Just for fun, schlage ich folgende linearen Ansatz (einfach, aber nicht wirklich effizient)

#include <type_traits> 

template <int ...> 
struct IntList 
{ }; 

template <int N, int ... Next> 
struct Generate : public Generate<N-1, N-1, Next...> 
{ }; 

template <int ... Next> 
struct Generate<0, Next ... > 
{ using type = IntList<Next ... >; }; 

int main() 
{ 
    static_assert(std::is_same<Generate<5>::type, 
           IntList<0, 1, 2, 3, 4>>{}, "!"); 
} 

Ein besserer Ansatz (aber nicht so einfach) kann die folgende (logarithmisch) sein

template <int...> 
struct IntList 
{ }; 

template <typename, typename> 
struct ConcatLists; 

template <int ... S1, int ... S2> 
struct ConcatLists<IntList<S1...>, IntList<S2...>> 
{ using type = IntList<S1..., (sizeof...(S1)+S2)...>; }; 

template <int N> 
struct Generate 
{ using type = typename ConcatLists< 
     typename Generate<(N>>1)>::type, 
     typename Generate<N-(N>>1)>::type>::type; }; 

template<> 
struct Generate<0> 
{ using type = IntList<>; }; 

template<> 
struct Generate<1> 
{ using type = IntList<0>; }; 

int main() 
{ 
    static_assert(std::is_same<Generate<5>::type, 
           IntList<0, 1, 2, 3, 4>>{}, "!");  
} 

- EDIT -

Die OP fragen

danke. Können Sie bitte erklären, wie das erste Beispiel funktioniert? Ich verstehe nicht, wie diese Zeile funktioniert: template <int N, int ... Next> struct Generate : public Generate<N-1, N-1, Next...> { };

Ich denke, der beste Weg zu verstehen, ist es die Kette folgt, die von Generate<5>, zu Inlist<0, 1, 2, 3, 4> bringen.

Generate<5> (5 unterscheidet sich von 0 so dass nur die Hauptversion von Generate anwendbar ist) erben (N ist 5; Next... leer ist) von Generate<4, 4>.

Generate<4, 4> (4 unterscheidet sich von 0) Vererben (N ist 5; Next... ist 4) aus Generate<3, 3, 4>.

Jetzt sollte klar sein.

Generate<3, 3, 4> erben von Generate<2, 2, 3, 4>.

Generate<2, 2, 3, 4> erben von Generate<1, 1, 2, 3, 4>.

Generate<1, 1, 2, 3, 4> erben von Generate<0, 0, 1, 2, 3, 4>.

Jetzt N ist Null. Also beide Versionen von Generate Spiel, aber die partielle Spezialisierung (struct Generate<0, Next ... >) ist spezialisierter und ist die verwendete ein und (Next... ist 0, 1, 2, 3, 4) haben wir

struct Generate<0, 0, 1, 2, 3, 4> 
{ using type = IntList<0, 1, 2, 3, 4>; }; 

Fazit: Generate<5> vererben Generate<0, 0, 1, 2, 3, 4> die type als IntList<0, 1, 2, 3, 4> definiert enthält.

+0

danke. Können Sie bitte erklären, wie das erste Beispiel funktioniert? Ich verstehe nicht, wie diese Zeile funktioniert: Vorlage struct Generiere: public Erzeuge {}; – user1786089

+1

@ user1786089 - Antwort verbessert; hoffe das hilft. – max66