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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15199833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:09:58  来源:igfitidea点击:

how to do an if else depending type of type in c++ template?

c++templates

提问by Joseph Mansfield

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

    }
};

I know how to write a template specialization and do a separate whole class def just for the char type.

我知道如何编写模板特化并为 char 类型做一个单独的整个类 def。

But what if I wanted to handle everything in just one block of code?

但是,如果我只想在一个代码块中处理所有事情怎么办?

How can I check if T is an int or a char?

如何检查 T 是 int 还是 char?

回答by Joseph Mansfield

You could use typeid:

你可以使用typeid

if (typeid(T) == typeid(int))

Or you could use the std::is_sametype trait:

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

if (std::is_same<T, int>::value)

回答by Andy Prowl

What you want is probably something like a compile-time if. Unfortunately, C++11 has no native support for such a language construct.

您想要的可能类似于编译时 if。不幸的是,C++11 没有对这种语言结构的原生支持。

However, if you just want to check whether two types are identical, the std::is_same<>type trait should help you:

但是,如果您只想检查两种类型是否相同,则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;
    }
};

However, keep in mind that the condition is evaluated at run-time, even though the value of is_same<T, int>::valueis known at compile-time. This means that boththe trueand the falsebranch of the ifstatement must compile!

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

For instance, the following would not be legal:

例如,以下情况是不合法的:

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

Also, as Xeocorrectly pointed out in the comments, the compiler will likely issue warnings because your condition will always evaluate to trueor to false, so one of the two branches will contain unreachable code.

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

回答by xvan

You may use explicit template specialization

您可以使用显式模板特化

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

回答by Xeo

How about a simple overload?

一个简单的重载怎么样?

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

(Note that the standard doesn't guarantee alphabetic order for the numeric values of a char.)

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

Then simply call that in increaseas return do_increase(element);.

然后只需将其调用increase为 as return do_increase(element);

回答by James Kanze

The usual solution here is to forward to an overloaded function with an additional argument. Something like:

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

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

With a little imagination, you can come up with all sorts of distinctions. If you make the target functions with the extra arguments templates, you can even leverage off SFINAE: design the dummy argument so that template type substitution fails, and the function will not be considered in the overload set. And since all of the functions are inline, it's probable that there will be no extra overhead, provided that you optimize.

稍加想象,你就可以想出各种各样的区别。如果您使用额外的参数模板制作目标函数,您甚至可以利用 SFINAE:设计虚拟参数,以便模板类型替换失败,并且不会在重载集中考虑该函数。而且由于所有函数都是内联的,如果您进行优化,很可能不会有额外的开销。

回答by NtscCobalt

This is along the lines of Andy Prowls answer but is all done at compile-time using a minimal helper class with specialization.

这与 Andy Prowls 的回答一致,但都是在编译时使用具有专业化的最小帮助程序类完成的。

In this instance you have a helper that actually does the specialization but you could also have the helper class just take a bool and then use something like std::is_same<T, int>::valueto pass that value as a template parameter.

在这种情况下,您有一个实际进行专业化的助手,但您也可以让助手类只获取一个布尔值,然后使用类似的东西std::is_same<T, int>::value将该值作为模板参数传递。

template <typename T>
struct myContainerHelper;
{
    // General Case
    static inline T increase(T element)
    {
        return ++element;
    }
};

template <>
struct myContainerHelper<char>
{
    // Specific case
    static inline char increase(char element)
    {
        if ((element>='a')&&(element<='z')) element+='A'-'a';
        return element;
    }
};

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

This allows you to only specialize the single function instead of the entire class. I'm using a template class with statics because I'm used to VS2012 limitations with partial specialization for function templates.

这允许您只专门化单个函数而不是整个类。我正在使用带有静态的模板类,因为我已经习惯了 VS2012 对函数模板的部分专业化的限制。