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.
-
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 ) + ... )> {};