web-dev-qa-db-fra.com

Tapez la condition dans le modèle

Est-il possible de construire seulement une partie du code étant donné le type du modèle en C++? Ce serait quelque chose de lac qui:

#include <iostream>

using namespace std;

template<typename T>
void printType(T param)
{
    #if T == char*
        cout << "char*" << endl;
    #Elif T == int
        cout << "int" << endl;
    #else
        cout << "???" << endl;
    #endif
}

int main()
{
    printType("Hello world!");
    printType(1);
    return 0;
}
37
Congelli501

Traits de type:

#include <iostream>
#include <type_traits> // C++0x
//#include <tr1/type_traits> // C++03, use std::tr1

template<typename T>
void printType(T param)
{
  if(std::is_same<T,char*>::value)
        std::cout << "char*" << endl;
  else if(std::is_same<T,int>::value)
        std::cout << "int" << endl;
  else
        std::cout << "???" << endl;
}

Ou encore mieux, il suffit de surcharger la fonction:

template<class T>
void printType(T partam){
  std::cout << "???" << endl;
}

void printType(char* partam){
  std::cout << "char*" << endl;
}

void printType(int partam){
  std::cout << "int" << endl;
}

La commande partielle veillera à ce que la fonction correcte soit appelée. De plus, la surcharge est préférable à la spécialisation de modèle dans le cas général, voir this et this artice pour savoir pourquoi. Peut ne pas s'appliquer à vous si vous devez totalement imprimer le type, car les conversions implicites sont prises en compte pour les fonctions surchargées.

50
Xeo

Utilisez la spécialisation de modèle:

template<typename T>
void printType(T param)
{
   // code for the general case - or omit the definition to allow only the specialized types
}

template<>
void printType<char*>(char* param)
{
   // code for char*
}

template<>
void printType<int>(int param)
{
   // code for int    
}

// ...
10

Vous pouvez utiliser une spécialisation. Le préprocesseur s'exécute avant tous les modèles et ne peut pas interagir avec eux.

template<typename T> void printType(T t) {
    std::cout << typeid(T).name(); // fallback
}
template<> void printType<char*>(char* ptr) {
    std::cout << "char*";
}
template<> void printType<int>(int val) {
    std::cout << "int";
}
6
Puppy

Depuis C++ 17, il existe un moyen de faire exactement cela avec if-constexpr. Les compilations suivantes depuis clang-3.9.1, gcc-7.1.0 et le récent compilateur MSVC 19.11.25506 se gèrent bien aussi avec une option/std: c ++ 17.

#include <iostream>
#include <type_traits>

template<typename T>
void printType(T)
{
    if constexpr (std::is_same_v<T, const char*>)
        std::cout << "const char*" << std::endl;
    else if constexpr (std::is_same_v<T, int>)
        std::cout << "int" << std::endl;
    else
        std::cout << "???" << std::endl;
}

int main()
{
    printType("Hello world!");
    printType(1);
    printType(1.1);
    return 0;
}

Production:

const char*
int
???
4
Wormer

Vous utilisez spécification de modèle pour spécifier les versions de votre fonction pour fonctionner différemment en fonction de son type. Par exemple, vous pouvez créer une version générique d'une fonction qui fonctionnerait avec la plupart des types, et créer une version spécifique pour par exemple int ce sera plus rapide. Vous le feriez de cette façon:

template <class T>
void printType(T param)
{
    cout<<"Generic version"<<endl;
}
template <>
void printType<int>(int param)
{
    cout<<"Int version"<<endl;
}
template <>
void printType<char>(char param)
{
    cout<<"Char version"<<endl;
}
//Rince and repeat.
3
Jesse Emond