Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;元编程:一个模板参数,它*必须*继承一个抽象类_C++_Templates_Inheritance_Metaprogramming - Fatal编程技术网

C++ C++;元编程:一个模板参数,它*必须*继承一个抽象类

C++ C++;元编程:一个模板参数,它*必须*继承一个抽象类,c++,templates,inheritance,metaprogramming,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:

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

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
{
  //...
};
模板类HashSet
{
//...
};
T是存储在这些集合中的值的类型。proto应该是T的一个实例,它被用作T类型的“null”值,用于集合包含。我对C++有着丰富的经验,但对TMP却不是特别熟悉,虽然它看起来像是一个很难简单地删除的东西,但我似乎无法理解C++中的伪代码<强> >类T继承密钥“< /强”是如何做到的。我希望能够创建C实例的哈希集,如:

HashSet<C, C::null> myset;
HashSet-myset;

有人能告诉我C++中处理这种情况的恰当的和惯用的方法吗?谢谢大家!

您可以使用
std::enable_,如果

template<class T, const T& proto, 
         std::enable_if_t<std::is_base_of<Key,T>::value>* = nullptr> 
class HashSet
{
  //...
};
这可能会更清楚一点,并为您提供一条更友好的错误消息,但您的类型约束不再在类声明中给出


有了它,我们将获得清晰、更好的错误消息,并在声明中保留我们的约束:

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
{};
模板
概念bool IsBaseOf=std::is_base_of::value;
模板
需要IsBaseOf
类哈希集
{};
有人能告诉我C++中处理这种情况的正确和习惯性的方法是什么吗?< /P> 那就是不处理它。如果用户传入一个从
键派生的类型,那么即使您没有在代码注释中添加该类型作为显式要求,模板实例化也会起作用。如果用户传入一个无效的模板参数,则可能会出现问题


<>下一个版本的C++可能会支持清楚地包含这些注释,但是在C++的当前版本中,尽管有一些技巧可以使用,除非在有限的情况下,惯用的方法是不用麻烦它。

和。我永远不会理解为什么隐藏在主模板的模板参数列表中的
std::enable\u优于用户友好的
static\u assert
message@PiotrSkotnicki我会说这是一个更好的错误之间的权衡消息,并将类型约束直接记录在声明中,而不是隐藏在定义中。幸运的是,这对于概念来说都是一个没有实际意义的问题。与简单地期望函数存在相比,需要这个基类有什么好处?你节省了虚拟功能和糟糕的设计。要使用int作为键吗?对不起,我不能那样做。你只是不小心比较了FooKey和BarKey?当然,编译器对此很满意,因为抽象函数的接口允许它。我想说,像
std::enable_if
这样的技巧已经成为事实上向用户和编译器表达类型约束的一种方式,但我想这是有争议的。@TartanLlama是的,我同意这一点,当表达类型约束时,如果
是惯用的表达方式,那么
std::enable_,但由于它被认为是一种黑客行为,表达类型约束只是一般还没有做到,至少从我所看到的情况来看是这样的。:)谢谢你。事实上,我甚至没有意识到它不会抱怨,除非我用一个不支持我使用的方法的t实例化了一个模板。我想它既不聪明到检查这个,也不聪明到让我优雅地做这个,所以。。。也许会平安无事。我将试用这些解决方案,然后再查看。非常感谢!哇,这在C++14中看起来真是“改进”。。。当然,这不是对你答案的评论。我很感激这个解决方案。谢谢是的,这太糟糕了。正如Piotr在评论中指出的,在类定义中可以使用<代码> STATICHYADSATE/来获得一点清晰和更好的错误消息,代价是在声明中记录了类型约束。@托马斯-这是C++方式。这是一个邪恶阴谋集团的阴谋,目的是将语言变成一种暴行,以保持低的采用率和高的工资;)
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
{};