C++ 元编程 : A template parameter which *must* inherit an abstract class

标签 c++ templates inheritance metaprogramming

我有一个用于可比较+哈希值的抽象类:

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_tstd::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 卡住了。

Live Demo


另一种选择是使用 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/

相关文章:

c++ - 4x4 矩阵重置缩放?

c++ - 如何实现中点位移

c++ - 将元组转换为模板中的结构

c++ - 调用传递给它的对象的成员方法的仿函数的部分模板特化

c++ - 重载解析如何在 private 修饰符的上下文中工作?

c++ - 使用大于为 src 分配的内存的计数调用 memcpy 是否安全?

c++ - 在多个容器中存储指向对象的指针

c++ - template<> 用于成员枚举的显式特化

java - 当继承跨不同的 JAR 时如何使用 @Entity 属性?

c++ - 通过未覆盖的基类从派生类调用函数