50 votes

modèle variadique récursif pour imprimer le contenu d'un pack de paramètres

Comment est-il possible de créer un modèle variadique récursif pour imprimer le contenu d'un pack de paramètres ? J'essaie avec ceci, mais il ne parvient pas à compiler:

 template <typename First, typename ...Args>
std::string type_name () {
    return std::string(typeid(First).name()) + " " + type_name<Args...>();
}
std::string type_name () {
    return "";
}

Comment dois-je mettre fin à la récursivité ?

32voto

user862857 Points 313

if constexpr C++17 vous permet de le faire dans une déclaration de modèle qui, contrairement à beaucoup d'anciennes solutions, est assez facile à comprendre :

 template <typename T, typename ...Args>
std::string type_name() {
  if constexpr (!sizeof...(Args)) {
    return std::string(typeid(T).name());
  } else {
    return std::string(typeid(T).name()) + " " + type_name<Args...>();
  }
}

12voto

Kerrek SB Points 194696

Comme alternative à la spécialisation partielle inexistante pour les fonctions, vous pouvez utiliser la surcharge sur une classe de typificateur :

 #include <string>
#include <iostream>
#include <typeinfo>

template <unsigned int N> struct NumberToType { };

template <typename T>
std::string my_type_name(NumberToType<0> = NumberToType<0>())
{
  return std::string(typeid(T).name());
}

template <typename T, typename ...Args>
std::string my_type_name(NumberToType<sizeof...(Args)> = NumberToType<sizeof...(Args)>())
{
  return std::string(typeid(T).name()) + " " + my_type_name<Args...>(NumberToType<sizeof...(Args)-1>());
}

int main()
{
  std::cout << my_type_name<int, double, char>() << std::endl;
}

7voto

skypjack Points 5516

Comme alternative, vous pouvez décompresser le pack de paramètres sur place comme dans l'exemple suivant :

 #include<string>
#include<iostream>
#include<typeinfo>

template <typename T, typename ...Args>
std::string type_name () {
    std::string str = typeid(T).name();
    int arr[] = { 0, (str += std::string{" "} + typeid(Args).name(), 0)... };
    (void)arr;
    return str;
}

int main() {
    auto str = type_name<int, double, char>();
    std::cout << str << std::endl;
}

La récursivité n'est pas nécessaire pour le faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X