类模板可以从其自身的完全特化中继承吗?

gct*_*gct 1 c++

我有一个数据类型,其中包含一些信息,并且可能会也可能不会存储额外的数据。我们称之为碎片。我定义了一个具有一些常见功能的基类:

class ShardBase {
public:
  virtual void Frobnicate() = 0;
};
Run Code Online (Sandbox Code Playgroud)

我想定义一个模板化的子类,允许访问额外的数据:

template <typename T=void>
class Shard : public ShardBase {
public:
  virtual const T& value() const = 0;
};
Run Code Online (Sandbox Code Playgroud)

我想处理没有额外数据的情况,所以我可以将 Shard 专门用于void

template <>
class Shard<void> : public ShardBase {};
Run Code Online (Sandbox Code Playgroud)

现在Shard<int>有了一个value()方法并且Shard<>只有基本功能。

我想做的继承Shard<T>Shard<void>,以便在任何不需要特定类型信息的地方,我都可以将const Shard<>&. 我知道在这种情况下我可以只使用 a const ShardBase&,但我想Shard<>与其他地方的 API 保持对称。

如果我做这样的事情:

template <typename T>
class Shard : public Shard<void> {
public:
  virtual const T& value() const = 0;
};

template <>
class Shard<void> : public ShardBase {};
Run Code Online (Sandbox Code Playgroud)

那么一切Shard<T>都会好起来Shard<>的,它会做我想做的事。但自然地,C++ 对我这样做会很生气:

<source>:87:22: error: implicit instantiation of template 'Shard<>' within its own definition
   87 | class Shard : public Shard<void> {
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我想要在这里做的事情似乎已经得到了很好的定义,那么有没有办法解决这个限制,或者我是 OoL 吗?

Tur*_*ght 5

如果类定义和专业化的顺序正确,这绝对是可能的。


该示例中的问题是主类定义出现在显式专业化之前:

template <typename T>
// Shard<void> is not yet known to be an explicit specialization here
//                   vvvvvvvvvvv
class Shard : public Shard<void> { 
public:
  virtual const T& value() const = 0;
};

template <>
class Shard<void> : public ShardBase {};

// only here the compiler knows that Shard<void> is an explicit specialization
Run Code Online (Sandbox Code Playgroud)

这可以通过前向声明 -class 来解决Shard,以便Shard<void>可以将显式特化放在 的定义之前Shard<T>

例如:神箭

struct ShardBase {};


template <typename T>
class Shard;

template <>
class Shard<void> : public ShardBase {};

template <typename T>
class Shard : public Shard<void> {
public:
  virtual const T& value() const = 0;
};
Run Code Online (Sandbox Code Playgroud)