2016-11-28 2 views
0

Dans mon projet, il y a une fonction définie par template pour trouver l'index d'un tuple, je ne comprends toujours pas comment ça marche: il semble y avoir une récursion mais je n'ai aucune idée de comment ça s'est terminé au bon index ?Comment ce modèle fonctionne-t-il pour trouver l'index d'un tuple?

// retrieve the index (for std::get) of a tuple by type 
// usage: std::get<Analysis::type_index<0, Type, Types ...>::type::index>(tuple) 
// TODO: should make this tidier to use 
template<int Index, class Search, class First, class ... Types> 
struct type_index 
{ 
    typedef typename Analysis::type_index<Index + 1, Search, Types ...>::type type; 
    static constexpr int index = Index; 
}; 

template<int Index, class Search, class ... Types> 
struct type_index<Index, Search, Search, Types ...> 
{ 
    typedef type_index type; 
    static constexpr int index = Index; 
}; 
+3

Je pense que l'auteur (s) respectif (s) aurait dû aller avec le 'TODO' en premier lieu ... ;-) –

+1

cela produira un message d'erreur * lovely * si le type' Search' n'est pas parmi ceux cherché ... – Walter

Répondre

3

La spécialisation est la condition de terminaison. Notez qu'il exige que First égal Search:

type_index<Index, Search, Search, Types ...> 
        ^^^^^^ ^^^^^^ 

Par exemple, si vous commencez avec

type_index<0, C, A, B, C, D>, 

cela ne se conforme pas à la spécialisation, de sorte que le modèle générique sera utilisé, la redirection (via son type membre) à

type_index<0, C, A, B, C, D>::type = type_index<1, C, B, C, D>::type 

mais ce n'est pas évaluables, soit jusqu'à ce que la chaîne atteigne

type_index<0, C, A, B, C, D>::type = ... = type_index<2, C, C, D>::type 

A ce stade, la spécialisation partielle peut être utilisé, qui dit que

type_index<2, C, C, D>::type = type_index<2, C, C, D> 
type_index<2, C, C, D>::index = 2 

et ainsi

type_index<0, C, A, B, C, D>::type::index = 2 
       ^^^^ 
       0 1 2 3 

comme prévu.


Notez que vous n'avez pas besoin de porter le Index autour et peut en effet laisser tomber toute chose ::type:

template<typename, typename...> 
struct type_index; 

template<typename Search, typename Head, typename... Tail> 
struct type_index<Search, Head, Tail...> { 
    // Search ≠ Head: try with others, adding 1 to the result 
    static constexpr size_t index = 1 + type_index<Search, Tail...>::index; 
}; 

template<typename Search, typename... Others> 
struct type_index<Search, Search, Others...> { 
    // Search = Head: if we're called directly, the index is 0, 
    // otherwise the 1 + 1 + ... will do the trick 
    static constexpr size_t index = 0; 
}; 

template<typename Search> 
struct type_index<Search> { 
    // Not found: let the compiler conveniently say "there's no index". 
}; 

Cela fonctionne comme:

type_index<C, A, B, C, D>::index 
    = 1 + type_index<C, B, C, D>::index 
    = 1 + 1 + type_index<C, C, D>::index 
    = 1 + 1 + 0 
    = 2 

et si le type n'est pas parmi la liste, dira quelque chose comme (GCC 6.2.1):

In instantiation of ‘constexpr const size_t type_index<X, C>::index’: 
    recursively required from ‘constexpr const size_t type_index<X, B, C>::index’ 
    required from ‘constexpr const size_t type_index<X, A, B, C>::index’ 
    required from [somewhere] 
error: ‘index’ is not a member of ‘type_index<X>’ 

que je trouve assez explicite.

+0

Merci beaucoup, mais j'ai encore quelques doutes. The'type_index <2, C, C, D> 'peut correspondre à la fois' template 'et' type_index ', pourquoi le compilateur a choisi la seconde un? –

+0

La résolution de spécialisation de modèle C++ (ainsi que la surcharge de fonction) concerne tout ce qui convient le mieux. Recherchez "Commande partielle" [ici] (http://fr.cppreference.com/w/cpp/language/partial_specialization) (et [ici] (http://fr.cppreference.com/w/cpp/language/ function_template # Function_template_overloading), respectivement). –

+0

Désolé, aurait dû dire: soit l'un des liens ci-dessus pour la résolution de spécialisation de modèle, [ici] (http://en.cppreference.com/w/cpp/language/overload_resolution) pour la résolution de surcharge (section "Meilleure fonction viable") . –