Введите условие в шаблоне - PullRequest
34 голосов
/ 06 июня 2011

Можно ли построить только некоторую часть кода с учетом типа шаблона в C ++? Это было бы нечто такое, что:

#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;
}

Ответы [ 5 ]

47 голосов
/ 06 июня 2011

Тип черты:

#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;
}

Или еще лучше, просто перегрузите функцию:

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;
}

Частичное упорядочение позаботится о том, чтобы была вызвана правильная функция. Кроме того, перегрузка предпочтительнее специализации шаблона в общем случае, см. this и this artice , почему. Может не подходить для вас, если вы полностью должны печатать тип, поскольку для перегруженных функций рассматриваются неявные преобразования.

9 голосов
/ 06 июня 2011

Используйте шаблон специализации:

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    
}

// ...
6 голосов
/ 06 июня 2011

Вы можете использовать специализацию. Препроцессор запускается перед всеми шаблонами и не может взаимодействовать с ними.

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";
}
4 голосов
/ 03 января 2018

Начиная с C ++ 17, есть способ сделать это с помощью if-constexpr. Следующие компиляции начиная с clang-3.9.1, gcc-7.1.0 и недавнего компилятора MSVC 19.11.25506 также хорошо справляются с опцией /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;
}

Выход:

const char*
int
???
3 голосов
/ 06 июня 2011

Вы используете шаблон спецификации , чтобы указать версии вашей функции для работы по-разному в зависимости от ее типа. Например, вы можете сделать универсальную версию функции, которая будет работать с большинством типов, и сделать специальную версию, например, для int это будет быстрее. Вы бы сделали это так:

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.
...