【问题标题】:Template member function specialization of a templated class without specifying the class template parameter模板化类的模板成员函数特化,无需指定类模板参数
【发布时间】:2022-01-10 04:29:59
【问题描述】:

在不指定类模板参数的情况下专门化模板化类的模板化成员函数的正确语法是什么?

这就是我的意思:

示例 #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(不编译:“封闭类模板未明确专门化”):

#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 工作?

【问题讨论】:

  • 你为什么要像这样打电话给c3.f,用&lt;int&gt;?你想达到什么目标?这对我来说有点奇怪,也许这是一个 XY 问题,对于底层用例有一些更直接的解决方案。
  • 在我真正的问题中,函数f 将一些信息发送到数据库。该函数可以作为不同对象类型的输入给出。确切发送的内容是通过使用A 类型的对象计算的(它被赋予C3 构造函数),因此它取决于类C3 模板参数。 C3类是一个模板类,继承自另一个模板类,它是其他模板化算法的输入参数,所以我不能改变接口。
  • 好的,您的示例中的专用模板参数 是否反映了函数 g 的返回类型?在这种情况下,会有一个简单的解决方案,因为系统实际上是过度参数化的。
  • 实际代码调用类A的几个成员函数,将B类型的函数f的参数转换为将要发送的信息。数据库表及其列取决于B,而数字的计算方式取决于A。将类型 A 视为计算器类型,而 B 是输入类型。

标签: c++ templates template-specialization function-templates class-template


【解决方案1】:

您可以使用一种称为标签调度的技术,并通过函数重载替换模板特化。

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

【讨论】:

  • 不,在这里您完全从代码中删除了对类型 B 的依赖。例如,将其视为void C3&lt;A&gt;::f&lt;int&gt;(void) const { std::cout&lt;&lt;A::g()+1&lt;&lt;std::endl; },而void C3&lt;A&gt;::f&lt;char&gt;(void) const { std::cout&lt;&lt;A::g()+2&lt;&lt;std::endl; } 即计算结果取决于AB:当Bint 时,您执行A::g()+1,而当Bchar 时,您执行A::g()+2
  • 我已经更新了我的示例 #3 以使其清楚。
  • 我明白了,我误会了。我已经相应地更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
相关资源
最近更新 更多