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
how to do an if else depending type of type in c++ template?
提问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_same
type 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>::value
is known at compile-time. This means that boththe true
and the false
branch of the if
statement must compile!
但是,请记住,条件是在运行时评估的,即使 的值is_same<T, int>::value
在编译时是已知的。这意味着,双方将true
与false
该分支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 true
or to false
, so one of the two branches will contain unreachable code.
此外,正如Xeo在评论中正确指出的那样,编译器可能会发出警告,因为您的条件将始终评估为true
或false
,因此两个分支之一将包含无法访问的代码。
回答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 increase
as 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>::value
to 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 对函数模板的部分专业化的限制。