在模板中键入条件

Con*_*501 35 c++ conditional templates

考虑到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;
}
Run Code Online (Sandbox Code Playgroud)

Xeo*_*Xeo 49

类型特征:

#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;
}
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,只是重载功能:

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;
}
Run Code Online (Sandbox Code Playgroud)

部分排序将注意调用正确的函数.此外,在一般情况下,重载比模板专业化更受欢迎,请参阅本文的原因.如果完全必须打印类型,可能不适用于您,因为隐式转换被认为是重载函数.

  • +1表示两种选择(并参考Sutter对模板专业化的看法)。我将指出,第二种方法“更好”,因为它更具可扩展性。值得注意的是,对于自定义类型,ADL需要第二种方法。 (2认同)

Wor*_*mer 16

从 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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

const char*
int
???
Run Code Online (Sandbox Code Playgroud)


Ale*_*ler 10

使用模板专业化:

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    
}

// ...
Run Code Online (Sandbox Code Playgroud)

  • Herb Sutter建议*not*使用模板特化(在函数上)并简单地使用常规过载.见http://www.gotw.ca/publications/mill17.htm (6认同)

Pup*_*ppy 6

您可以使用专业化.预处理器在所有模板之前运行,不能与它们交互.

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";
}
Run Code Online (Sandbox Code Playgroud)

  • 哇!让我们很酷:)重载*肯定*解决了问题,正如Xeo所证明的那样.专业化的问题是,如果你(突然)在`char*`specialization*之后引入`template <typename T> void printType(T*t);`overload*,那么`char*c; printType(c);`将调用这个新的重载而不是"直观预期"的专业化:http://ideone.com/F1xS7 (8认同)
  • @Matthieu:我没有给Sutter推荐的废话.我的代码解决了OP的问题,即使他没有采取任何论据.重载肯定不会. (2认同)