我有一个类模板如下:
template<class T>
class A;
什么时候T是 a Pair<T1, T2>,我专门研究它。
template<class T1, class T2>
class A<Pair<T1, T2>>;
我有一个派生自 Pair 的类
class D : public Pair<int, char>
{};
当我使用时A<D>,我希望它使用专门的版本,但它没有。我有许多派生自 Pair 或其他专门版本的类。如何自动完成?
它不起作用的原因是因为您将它专门用于 pair,而不是从 pair 继承的类(顺便说一句,从 stdlib 类继承通常是个坏主意)。您可以将其专门用于D.
template<class T>
struct A {
A(){cout << "not special\n";}
};
template<class T1, class T2>
struct A<pair<T1, T2>> {
A(){cout << "special\n";}
};
struct D : public pair<int, char>
{};
template<>
struct A<D> {
A(){cout << "special D\n";}
};
int main() {
A<D> a;
return 0;
}
输出special D
您也可以使用std::is_base_of,但这会很痛苦,我建议不要使用。如果你对这样做的死心塌地,你可以有另一个像这样的课程
template <typename T, bool B>
struct helper;
template <typename T>
struct helper<T,true>;
template <typename T>
struct helper<T,true>;
然后您可以在第一个类中创建该类,例如
template<class T>
struct A {
helper<T,is_base_of<pair<int,char>,T>::value> h;
};
这应该让你开始我会让你弄清楚其余的:)。
这是一个更简洁的版本,只有一个类。
template<class T,bool B = is_base_of<pair<int,char>,T>::value>
struct A;
template<class T>
struct A<T,true> {
A(){cout << "special\n";}
};
struct D : public pair<int, char>
{};
template<class T>
struct A<T,false> {
A(){cout << "not special\n";}
};
int main() {
A<D> a;
A<int> b;
return 0;
}
“永远不要从标准类型派生,它们并不意味着派生。派生可能会导致 UB”
D是一种不同的类型pair<int,char>(尽管是从它派生的)。模板参数推导不考虑类型之间的转换能力。它只匹配类型。
现在对于您想要调用专用版本的情况,您可以使用标签调度和助手。
以下代码可能对您有所帮助:
template<class T> //Primary class template
class A
{//impl..};
template<class T1, class T2> //explicit specialization
class A<pair<T1, T2>>
{
public:
A(){std::cout << "A<pair>\n";}
};
template<typename T1,typename T2, bool b> //type selector utility, dispatched to this
struct AP{typedef A<T1> type;}; // type if passed type is not a
//derived class of pair.
template<typename T1,typename T2>
struct AP<T1,T2,std::true_type::value>
{
typedef A<pair<T1,T2>> type; //only if passed type is derived from pair
};
class D : public pair<int, char>
{}; //type derived from pair
class E{}; //some other type
template<typename pair,typename t> //helper class to do the dirty job
struct APH
{
using fsttyp = typename pair::first_type;
using sndtyp = typename pair::second_type;
typedef typename AP<fsttyp,sndtyp,is_base_of<pair,t>::value>::type type;
};
int main()
{
APH<pair<int,char>,D>::type a;// a is of A<pair<int,char>> type
APH<pair<int,char>,E>::type a;// a is of A<E> type
return 0;
}