如何在c ++模板中执行if else依赖类型?

32 c++ templates

// template specialization
#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase () {

    //if(T.type==int)//how to do this or something similar?
    //do this if an int
    return ++element;

    //if(T.type==char)
     //if ((element>='a')&&(element<='z'))
      //element+='A'-'a';
      //return element;

    }
};
Run Code Online (Sandbox Code Playgroud)

我知道如何编写模板特化并为char类型执行单独的整个类def.

但是,如果我只想在一个代码块中处理所有内容呢?

如何检查T是int还是char?

Jos*_*eld 32

你可以使用typeid:

if (typeid(T) == typeid(int))
Run Code Online (Sandbox Code Playgroud)

或者您可以使用std::is_same类型特征:

if (std::is_same<T, int>::value)
Run Code Online (Sandbox Code Playgroud)

  • @JosephMansfield您提供的链接无预览. (4认同)
  • C ++ 17引入了constexpr if,这可能就是您想要的。 (3认同)
  • 对于`static_if`有很多提议,但都有问题.SG8最近写了[对提案的分析](https://docs.google.com/viewer?a=v&pid=forums&srcid=MDIyMDc3NjUwMTczOTM0Mjk3NjABMDI2MzM3MjkxNDM4NDQ5MzE4NDcBLWVsS1Y4dFhtdDhKATUBaXNvY3BwLm9yZwF2Mg&authuser=0). (2认同)

And*_*owl 15

你想要的可能就像编译时一样.不幸的是,C++ 11对这种语言结构没有本机支持.

但是,如果您只想检查两种类型是否相同,那么std::is_same<>类型特征应该可以帮助您:

#include <type_traits> // <== INCLUDE THIS STANDARD HEADER

// class template:
template <class T>
class mycontainer 
{
    T element;
public:
    mycontainer (T arg) {element=arg;}
    T increase () 
    {
        if (std::is_same<T, int>::value)   // <== THIS IS HOW YOU WOULD USE IT
            return ++element;

        if (std::is_same<T, char>::value)  // <== THIS IS HOW YOU WOULD USE IT
        {
            if ((element>='a') && (element<='z'))
                element+='A'-'a';
        }

        return element;
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,请记住,在运行时评估条件,即使is_same<T, int>::value在编译时已知值.这意味着,双方truefalse该分支if语句必须编译!

例如,以下内容不合法:

if (std::is_same<T, int>::value)
{
    cout << element;
}
else if (std::is_same<T, my_class>::value)
{
    element->print();  // Would not compile when T is int!
}
Run Code Online (Sandbox Code Playgroud)

此外,正如Xeo在注释中正确指出的那样,编译器可能会发出警告,因为您的条件将始终评估为truefalse,因此两个分支中的一个将包含无法访问的代码.


xva*_*van 8

您可以使用显式模板专门化

#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase();
};


template<>
int mycontainer<int>::increase(){
    return ++element;
}

template<>
char mycontainer<char>::increase(){
    if ((element>='a')&&(element<='z'))
       element+='A'-'a';
    return element;
}

int main(){
        mycontainer<int> A(10);
        mycontainer<char> B('x');

        cout << A.increase() <<endl;
        cout << B.increase() <<endl;
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个解决方案 (2认同)

Xeo*_*Xeo 7

一个简单的过载怎么样?

// in the private section
static int& do_increase(int& i){ return ++i; }
static char& do_increase(char& c){
  if(c >= 'a' && c <= 'z')
    c += 'A' - 'a';
  return c;
}
template<class U>
static U& do_increase(U& arg){
  // some default implementation?
  return arg;
}
Run Code Online (Sandbox Code Playgroud)

(请注意,标准不保证a的数值的字母顺序char.)

然后,只需在调用increasereturn do_increase(element);.


Jam*_*nze 5

这里通常的解决方案是转发到带有附加参数的重载函数。就像是:

template <typename T>
class MyContainer
{
    T increase( int const* ) { /* special treatment for int */ }
    T increase( ... )        { /* default treatment         */ }
public:
    T increase()
    {
        return increase( (T const*)0 );
    }
};
Run Code Online (Sandbox Code Playgroud)

只要发挥一点想象力,您就可以想出各种区别。如果您使用额外的参数模板创建目标函数,您甚至可以利用 SFINAE:设计虚拟参数,以便模板类型替换失败,并且该函数不会在重载集中被考虑。由于所有函数都是内联的,因此只要您进行优化,很可能不会产生额外的开销。