我有一个用于可比较+哈希值的抽象类:
class Key
{
public:
virtual bool operator ==(const Key&) const = 0;
virtual bool operator !=(const Key&) const = 0;
virtual u32 hashcode() const = 0;
};
还有一些继承这个的具体类 C。
class C : public Key
{
private:
u32 a, b;
public:
static const C& null; // a prototype for representing a "no value" C
// Some reasonable implementation; it's just a pair
// ...
};
我想实现一个模板化的 HashSet 类:
template<class T inherits Key, const T& proto> class HashSet
{
//...
};
T 是存储在这些集合中的值的类型。 proto 应该是 T 的一个实例,它用作 T 类型的“空”值,用于集合包含。我对 C++ 有相当的经验,但对 TMP 不是特别有经验,虽然它看起来应该很容易实现,但我似乎无法弄清楚我的伪代码 "class T inherits Key" 实际上是用 C++ 完成的。我希望能够创建 C 实例的哈希集,例如:
HashSet<C, C::null> myset;
谁能告诉我在 C++ 中处理这种情况的正确和惯用的方法是什么?谢谢!
最佳答案
您可以使用 std::enable_if_t
和 std::is_base_of
为此:
template<class T, const T& proto,
std::enable_if_t<std::is_base_of<Key,T>::value>* = nullptr>
class HashSet
{
//...
};
现在 HashSet
实例化仅在 T
时有效继承自 Key
.
std::enable_if_t
是一个 C++14 特性。您可以使用typename std::enable_if<...>::type
如果你被 C++11 卡住了。
另一种选择是使用 static_assert
:
template<class T, const T& proto>
class HashSet
{
static_assert(std::is_base_of<Key, T>::value, "T must inherit from Key");
};
这可能更清楚一点,并给你一个更友好的错误消息,但你的类型约束不再在类声明中给出。
与 Concepts我们将获得清晰、更好的错误消息,并在声明中保留我们的约束:
template <class Base, class Derived>
concept bool IsBaseOf = std::is_base_of<Base, Derived>::value;
template<class T, const T& proto>
requires IsBaseOf<Key,T>
class HashSet
{};
关于C++ 元编程 : A template parameter which *must* inherit an abstract class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33033340/