根据 Derived 中的值检查基类的模板参数

Posted

技术标签:

【中文标题】根据 Derived 中的值检查基类的模板参数【英文标题】:Check template argument of Base class against values in Derived 【发布时间】:2014-11-13 20:16:06 【问题描述】:

假设我有一个像

这样的接口类(虚构的例子,不是真实的代码)
template <int year>
class Car 
public: 
  virtual void move(double x, double y) = 0;
  // etc etc
;

还有很多派生类,比如

template <int year>
class Model8556 : virtual public Car<year> 
private: 
  void move(double x, double y) 
    // ...
  
  int yearMax = 2000; // different for every model
  int yearMin = 1990;
  // etc etc
;

我通过某处选择模型

Car<foo>* myCar;    
switch (bar) 
  case 1: myCar = new model3434<foo>(); break;
  case 2: myCar = new model8295<foo>(); break;
  // etc

我确实想在编译时检查 Car(或更好:派生类)的模板参数。我希望模板参数 year 保持在一定范围内(即 yearMin 和 yearMax 之间)。但是:这个特定范围在派生类之间有所不同。 (编辑:)由于有很多派生类,我更喜欢 Car 中的解决方案。

我怎样才能实现这种行为?或者这是糟糕的设计?

感谢任何帮助。

【问题讨论】:

试试static_assert。 en.cppreference.com/w/cpp/language/static_assert 您确定需要使用虚拟继承吗? @NO_NAME:与什么相反?你建议“正常”继承吗?接口是否有经验法则? @mstrkrft ...规则是,如果不需要,则不要使用虚拟继承。 @mstrkrft 虚拟继承在您使用多重继承时非常有用。 【参考方案1】:

你是这个意思吗?

template <int year>
class Model8556 : virtual public Car<year> 
private: 

  static const int yearMax = 2000; // I assume you meant a static constant
  static const int yearMin = 1990;

  static_assert( yearMin <= year && year <= yearMax,        // Condition
                 "Invalid template argument specified!" );  // Error message
;

Demo. 不可能用当前方法把它放到基类中; CRTP 不起作用,因为派生类在Car 中将被视为不完整。不过,改变结构可能会有所帮助。

template <int year>
class Car

    // Your implementation, as above
;

template <int year,
          int YearMin,
          int YearMax>
class CarChecker : Car<year>

    // Optionally declare constants here

    static_assert( YearMin <= year && year <= YearMax,
                   "Invalid template argument specified!" );
;

template <int year>
class Model8556 :
    public CarChecker<year, 1990, 2000> // Specify the minimum and maximum here
;

【讨论】:

我忘了说:我希望这个检查在基类中,因为有很多派生类。这可能吗? @mstrkrft 提出了解决方案。 实际上,这不适用于上面提到的 switch 语句,因为 Car 指针需要他的模板参数。抱歉,我之前没有正确测试过。 @mstrkrft 再看第二个版本,我调整好了

以上是关于根据 Derived 中的值检查基类的模板参数的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Derived 内部调用 Base 实例中的受保护成员函数?

检查初始化列表中的空向量

虚函数与作用域

将共享指针的派生类切换到基类

如何使用在同一类的基模板中的类中声明的枚举

派生类不从基类继承重载方法