【问题标题】:C++ Partial-specialization of class in source not header源代码中类的 C++ 部分特化而不是标头
【发布时间】:2015-03-05 13:41:46
【问题描述】:

Foo.h

template<typename A, typename B>
class Foo{
public:
  Foo();
  /*..*/
};

Foo.cpp

template<typename A, typename B>
Foo<A, B>::Foo(){/*...*/}

template<typename A>
Foo<A, Beta>::Foo(){/* some specialized construction */} //<- this doesn't work.

template<>
Foo<Alpha, Beta>::Foo(){/*...*/} // <-will work, but I want partial specialization.

当我编译时,部分专用的构造函数会抛出错误

用于声明的嵌套名称说明符 'Foo::' 不引用类、类模板或类模板部分特化

我想我需要在某个地方声明这个部分专业化的类,但我不想一直重新声明同一个类......即我不想把以下内容放在标题中文件:

template<typename A>
class Foo_Beta : public Foo<A, Beta>{
public:
  Foo_Beta();
}

//in cpp
template<typename A>
Foo_Beta<A>() : Foo<A, Beta>() {/**specialized constructor stuff**/}

因为那时我无法构造使用 Foo_Beta 构造函数的 Foo()

我试过了

template<typename A>
class Foo<A,Beta> : public Foo<A, Beta>{
public:
  Foo();
}

但这也不能编译。

本质上,声明一个类的部分特化而不重新声明该类的所有内部函数的语法是什么?

【问题讨论】:

  • 部分特化仍然是一个模板;你为什么要把它放在一个 .cpp 文件中?无论如何,问题似乎更多是关于如何在不替换整个类的情况下部分专门化类模板的成员函数。不幸的是,这是不可能的。您不能部分特化函数模板,其中包括类模板的成员函数。
  • 您使用Foo_Beta 显示的示例不是部分专业化。部分专业化将是例如template&lt;typename A&gt; class Foo&lt;A, Beta&gt; { ... };
  • @SebastianRedl:我怀疑可能是这样。我想要的主要是一个干净的“如果您以这种方式获得 Beta 构造,则以另一种方式获得 Beth,A 是 Alpha 还是 Aleph 并不重要。”但是,除了构造函数之外,该类对于它将接收的任何组合 A、B 的行为都是相同的。

标签: c++ partial-specialization template-classes


【解决方案1】:

你说:

template<typename A> Foo<A, Beta>::Foo(){/* some specialized construction */} //<- this doesn't work.

只有当你专攻整个班级时,你才能使用它。您不能只专门化该类的一个成员函数。

以下应该有效:

template<typename A> class Foo<A, Beta>
{
   Foo();
};

template<typename A> 
Foo<A, Beta>::Foo()
{
}

【讨论】:

  • “我想我需要在某个地方声明这个部分专业化的类,但我不想一直重新声明同一个类......”
  • @0x499602D2 如果现实是我必须不断重新声明课程,那就是现实。我猜这很糟糕......但这可能只是语法的限制
  • @r-sahu,我必须将template&lt;typename A&gt; class Foo&lt;A, Beta&gt; { Foo(); }; 添加到标题中,还是可以在源文件中?另外,我的意思是……他们还有很多其他共同的功能,我需要在专业化中包含这些功能吗?
  • @shavera,这两个问题的答案都是“是”。一旦创建了类模板的特化,它就与原始类模板无关。
  • @r-sahu,呃。这变得令人沮丧。我认为这可能会回到整个设计的绘图板上。我对模板类有一些假设,我想这些假设根本不成立。这太糟糕了,因为最终这似乎是正确的方法......
【解决方案2】:

正如其他人所提到的 - 你不能部分专门化一个函数。但是,您可以将模板函数中的工作推迟到专门的实现函数中,这确实会产生部分专门化的效果,例如:

template<class X>
X make_a_B()
{
    return X();  // default implementation
}

template<>
Beta make_a_B<Beta>()
{
    Beta b;
    // do custom things with b...
    return b;  // fully specialised for Beta, everything else uses default case.
}

template<class X>
X make_an_A()
{
    return X();
}

template<typename A, typename B>
class Foo{
public:
    Foo()
    : _myA( make_an_A<A>() )
    , _myB( make_a_B<B>() )
    {}

    /*..*/
    A _myA;
    B _myB;
};

Foo&lt;Alpha, Beta&gt;() 现在的行为与 Foo&lt;Alpha, Gamma&gt;() 不同

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多