这是earlier question的续集问题(关于不同的主题)。下面的代码包含了Dehstil关于使用专业化的建议。
具有模板模板参数的函数应该如何专门化?
下面的代码(两个专业化行不编译)使问题具体化。
#include <cassert>
template<typename S> struct PA1 {};
template<typename S> struct PA2 {};
template<typename S> struct PB {};
template<typename S> struct PC {};
template<typename S> struct A1 { typedef PA1<S> P; };
template<typename S> struct A2 { typedef PA2<S> P; };
template<typename S> struct B { typedef PB <S> P; };
template<typename S> struct C { typedef PC <S> P; };
template<typename S, template<typename> class T> char fn(typename T<S>::P);
template<typename S, template<typename> class T> char fn(typename T<S>::P)
{
return 'a';
}
template<typename S> char fn<B<S> >(B<S>::P) { return 'b'; }
template<typename S> char fn<C<S> >(C<S>::P) { return 'c'; }
int main()
{
PA1<int> pa1;
PA2<int> pa2;
PB<int> pb;
PC<int> pc;
assert( (fn<int, A1>(pa1)) == 'a' );
assert( (fn<int, A2>(pa2)) == 'a' );
assert( (fn<int, B>(pb)) == 'b' );
assert( (fn<int, C>(pc)) == 'c' );
}
四个函数调用fn&lt; ...,...&gt;()在调用时具有相同的签名非常重要,因为它们本身将驻留在适用于四个类A1 / A2 / B /的模板类中下进行。
答案 0 :(得分:3)
C ++标准不允许部分专业化功能模板!
重载您的功能,而不是专门化它们。
阅读Herb Sutter关于Why Not Specialize Function Templates? 的解释
然后阅读为什么要超载而不是专门化:Template Specialization and Overloading 作者:Herb Sutter
编写一个类模板call
并将它们专门化为:
template<class S, template<typename> class T>
struct call
{
static char fn(typename T<S>::P &p)
{
return ::fn<S,T>(p);
}
};
template<class S>
struct call<S,B>
{
static char fn(typename B<S>::P &p)
{
return ::fn<S>(p);
}
};
template<class S>
struct call<S,C>
{
static char fn(typename C<S>::P &p)
{
return ::fn<S>(p);
}
};
然后您可以使用此类模板统一调用所有函数:
assert( (call<int, A1>::fn(pa1)) == 'a' );
assert( (call<int, A2>::fn(pa2)) == 'a' );
assert( (call<int, B>::fn(pb)) == 'b' );
assert( (call<int, C>::fn(pc)) == 'c' );
参见在线演示:http://www.ideone.com/TISIT
还请注意ideone.com(上面的链接)
中完整解决方案中的重载功能模板答案 1 :(得分:1)
功能只能完全专业化。使用函数重载:
template<typename S> char fn(typename B<S>::P) { return 'b'; }
template<typename S> char fn(typename C<S>::P) { return 'c'; }