在C++范型编程中如何只特化类的一个成员函数(二)
某个成员函数的方法是多种多样的。针对上面这种情况,个人其实最推荐方法2,我们没必要把简单的问题复杂化。
下面我们考虑另外一个需求, 当模板类的某个参数是某种类型时, 我们要求特化其中的一个成员函数:
template
struct Base
{
//other function
//....
void Func(){ cout << "primary function" << endl; }
};
void test2()
{
Base a;
a.Func();
Base b;
b.Func();
}
int main()
{
test2();
}
要求上面的模板类如果T2 是string类型, 我们要求对Func特殊重写,其他的成员函数无论什么情况实现都是一样的。
有了上面的那个例子的实现经验, 对这个问题我们解决就方便多了。
方法1:
template
struct Base
{
//other function
//....
void Func()
{
if(typeid(std::string) == typeid(T2))
{
cout<<"specialization function"<
}
else
{
cout << "primary function" << endl;
}
}
};
点评:通过运行时类型识别(RTTI)实现,需要打开相关编译选项,并且低效。
方法2:
template
struct Base
{
//other function
//....
template
void FuncImpl()
{
cout << "primary function" << endl;
}
template<>
void FuncImpl()
{
cout << "specialization function" << endl;
}
void Func()
{
FuncImpl();
}
};
点评:通过成员函数特化实现
方法3:
template
struct Base
{
//other function
//....
template
class Type2Type
{
typedef T type;
};
template
void FunImpl(const Type2Type)
{
cout << "primary function" << endl;
}
template
void FunImpl(const Type2Type)
{
cout << "specialization function" << endl;
}
void Func()
{
FunImpl(Type2Type());
}
};
点评: 通过函数重载实现
方法4:
template
struct IsString
{
enum { value = false };
};
template<>
struct IsString
{
enum { value = true };
};
template
struct Base
{
//other function
//....
void Func()
{
if(IsString::value)
{
cout << "specialization function" << endl;
}
else
{
cout << "primary function" << endl;
}
}
};
点评: 通过编译时类型判断实现。
方法5:
template
struct must_be_same_type
{
enum { ret = 0 };
};
template<>
struct must_be_same_type
{
enum { ret = 1 };
};
template < typename T1,typename T2 >
class Base{
public:
//other function
//....
void Func(){
if(must_be_same_type::ret)
{
cout << "specialization function" << endl;
}
else
{
cout << "primary function" << endl;
}
}
};
点评: 和方法4类似, 是不过实现方式不一样。
最后,探讨下我自己遇到的问题, 我们在写一个事件委托(delegate)类,大概如下:
template
class CEvent
{
public:
//other function
//....
return_type operator()(first_type p1, second_type p2)
{
return_type ret = return_type();
//...
//ret = invoker(p1, p2);
return ret;
}
};
void test3()
{
CEvent e1;
e1(1, 2);
CEvent e2;
e2(1, 2);
}
int main()
{
test3();
}
我们可以看到,当return_type是void时, 因为没有返回值,上面的代码会编译失败,因此我们只能偏特化这种情况:
template
class CEvent
{
public:
//other function
//....
void operator()(first_type p1, second_type p2)
{
//...
//invoker(p1, p2);
return;
}
};
但是,我们会发现只有这个operator()函数是需要根据return_type特殊对待的,其他函数永远都是一样的。
我们现在的问题就是如何只特化这个函数。
首先我们会想到如下的实现方法:
template
struct IsVoid
{
enum { value = false };
};
template<>
struct IsVoid
{
enum { value