我有一个数据类型,其中包含一些信息,并且可能会也可能不会存储额外的数据。我们称之为碎片。我定义了一个具有一些常见功能的基类:
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 吗?
如果类定义和专业化的顺序正确,这绝对是可能的。
该示例中的问题是主类定义出现在显式专业化之前:
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)