未指定 class 模板参数的模板化 class 模板成员函数特化
Template member function specialization of a templated class without specifying the class template parameter
在不指定 class 模板参数的情况下特化模板化 class 的模板化成员函数的正确语法是什么?
我的意思是:
示例 #1(有效):
#include <iostream>
struct C1
{
template <class B>
void f(void) const;
};
template <>
void C1::f<int>(void) const { std::cout<<777<<std::endl; }
int main(void)
{
C1 c1; c1.f<int>();
}
示例 #2(有效):
#include <iostream>
template <class A>
struct C2
{
template <class B>
void f(void) const;
};
template <>
template <>
void C2<int>::f<int>(void) const { std::cout<<888<<std::endl; }
int main(void)
{
C2<int> c2; c2.f<int>();
return 0;
}
示例 #3(不编译:“封闭 class 模板未明确专门化”):
#include <iostream>
template <class A>
struct C3
{
template <class B>
void f(void) const;
};
struct D { static int g(void){ return 999; } };
template <class A>
template <>
void C3<A>::f<int>(void) const { std::cout<<A::g()+1<<std::endl; }
template <class A>
template <>
void C3<A>::f<char>(void) const { std::cout<<A::g()+2<<std::endl; }
int main(void)
{
C3<D> c3a; c3a.f<int >(); // expect to see 1000
C3<D> c3b; c3b.f<char>(); // expect to see 1001
return 0;
}
如何使示例 #3 起作用?
您可以使用一种称为标记分派的技术,并用函数重载替换模板特化。
template<typename>
struct Tag {};
template <class A>
struct C3
{
void f_impl(Tag<int>) const;
void f_impl(Tag<char>) const;
template<class B>
void f() const {
f_impl(Tag<B>{});
}
};
struct D { static int g(void){ return 999; } };
template <class A>
void C3<A>::f_impl(Tag<int>) const { std::cout<<A::g()+1<<std::endl; }
template <class A>
void C3<A>::f_impl(Tag<char>) const { std::cout<<A::g()+2<<std::endl; }
然后您的呼叫站点看起来完全符合您的要求:
C3<D> c3; c3.f<int>(); // expect to see 1000
C3<D> c4; c4.f<char>(); // expect to see 1001
完整示例here。
在不指定 class 模板参数的情况下特化模板化 class 的模板化成员函数的正确语法是什么?
我的意思是:
示例 #1(有效):
#include <iostream>
struct C1
{
template <class B>
void f(void) const;
};
template <>
void C1::f<int>(void) const { std::cout<<777<<std::endl; }
int main(void)
{
C1 c1; c1.f<int>();
}
示例 #2(有效):
#include <iostream>
template <class A>
struct C2
{
template <class B>
void f(void) const;
};
template <>
template <>
void C2<int>::f<int>(void) const { std::cout<<888<<std::endl; }
int main(void)
{
C2<int> c2; c2.f<int>();
return 0;
}
示例 #3(不编译:“封闭 class 模板未明确专门化”):
#include <iostream>
template <class A>
struct C3
{
template <class B>
void f(void) const;
};
struct D { static int g(void){ return 999; } };
template <class A>
template <>
void C3<A>::f<int>(void) const { std::cout<<A::g()+1<<std::endl; }
template <class A>
template <>
void C3<A>::f<char>(void) const { std::cout<<A::g()+2<<std::endl; }
int main(void)
{
C3<D> c3a; c3a.f<int >(); // expect to see 1000
C3<D> c3b; c3b.f<char>(); // expect to see 1001
return 0;
}
如何使示例 #3 起作用?
您可以使用一种称为标记分派的技术,并用函数重载替换模板特化。
template<typename>
struct Tag {};
template <class A>
struct C3
{
void f_impl(Tag<int>) const;
void f_impl(Tag<char>) const;
template<class B>
void f() const {
f_impl(Tag<B>{});
}
};
struct D { static int g(void){ return 999; } };
template <class A>
void C3<A>::f_impl(Tag<int>) const { std::cout<<A::g()+1<<std::endl; }
template <class A>
void C3<A>::f_impl(Tag<char>) const { std::cout<<A::g()+2<<std::endl; }
然后您的呼叫站点看起来完全符合您的要求:
C3<D> c3; c3.f<int>(); // expect to see 1000
C3<D> c4; c4.f<char>(); // expect to see 1001
完整示例here。