// 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)
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在编译时已知值.这意味着,双方将true与false该分支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在注释中正确指出的那样,编译器可能会发出警告,因为您的条件将始终评估为true或false,因此两个分支中的一个将包含无法访问的代码.
您可以使用显式模板专门化
#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)
一个简单的过载怎么样?
// 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.)
然后,只需在调用increase的return do_increase(element);.
这里通常的解决方案是转发到带有附加参数的重载函数。就像是:
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:设计虚拟参数,以便模板类型替换失败,并且该函数不会在重载集中被考虑。由于所有函数都是内联的,因此只要您进行优化,很可能不会产生额外的开销。