Template-Metaprogrammierung



  • Auf der Suche nach einer Möglichkeit den Index eines Types in einem Tupel herauszufinden, bin ich auf folgende Möglichkeit gestoßen:

    template < typename T, typename Tuple > 
    struct Index;
    
    template < typename T, typename... Types> 
    struct Index<T, std::tuple<T, Types...>> {
    	static const std::size_t value = 0;
    };
    
    template < typename T, typename U, typename... Types > 
    struct Index<T, std::tuple<U, Types...>> {
    	static const std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
    };
    

    Allerdings verstehe ich nicht, wie das Ganze funktioniert. 😃 Wäre nett, wenn mir jemand erklären könnte wie denn jetzt genau für jeden Typ der Index herausgefunden wird.

    Danke schon einmal im Voraus ! 👍



  • Das Template Index 1 ist lediglich dazu da, bestimmte Templatespezialisierungen erstellen zu können, also Index 2 und 3. Wie Templatespezialisierungen funktionieren, weißt du hoffentlich.
    Nun kann man eine Instanz von Index erstellen, dessen erstes Templateargument der zu suchende Typ T und das zweite der zu durchsuchende Tupel ist. Index 2 wird vom Kompiler gewählt, wenn der zu suchende Typ T der erste im Tupel vorkommende Typ ist. Value, also der Index ist demnach 0. Types... ist ein Template-Parameterpack und enthält die Typen, die nach T im Tupel stehen.
    Index 3 wird vom Kompiler gewählt, wenn der zu suchende Typ T nicht der erste Typ im Tupel ist, sondern ein Typ U der erste ist. Types... enthält wieder den Rest, der nach U kommt.
    Nun sind Index 1 und 2 rekursiv miteinander verknüpft. Index 3 instanziiert nämlich wiederum einen Index, wobei entweder Spezialisierung Index 1 oder 2 aufgerufen wird. Dabei übergibt Index 3 wieder den zu suchenden Typ und den Rest, welcher nach U kommt, rückt also eins nach vorne. Irgendwann wird nun Index 2 instanziiert, und die Rekursion ist am Ende angelangt.


  • Mod

    Dank fold expressions geht das in C++17 dann direkt ohne Rekursion:

    template <typename T, typename Tuple, typename = std::make_index_sequence<std::tuple_size<Tuple>{}>>
    struct Index;
    template <typename T, typename... Types, typename... indexes>
    struct Index<T, std::tuple<Types...>, std::index_sequence<indexes...>>
        : std:: integral_constant<std::size_t, ( ( std::is_same<T, Types>{} * indexes ) + ... )> {};
    

Anmelden zum Antworten