检查派生中基类的模板参数
Check template parameter of Base class in Derived
我有一个像
这样的基类template <int parameter>
class Base {
public:
virtual int getMaxParameter() = 0;
}
,我选择了多个派生类中的一个,比如
template <int parameter>
class DerivedA : public Base<parameter>
{
public:
int getMaxParameter() { return 2; }
}
通过const int p = 3;
Base<p>* base;
switch (unreleated_input_int) {
case 1:
base = new DerivedA<p>(); break;
case 2:
base = new DerivedB<p>(); break;
// ...
}
问:如何确保Base &派生不超过getMaxParameter()的返回值?
我可以这样写
DerivedA() {
if (parameter > getMaxParameter())
//...
}
但是我不想在每个派生类中都写这个。我能在Base中做这样的事情吗?我不能调用纯虚函数,但还有其他方法吗?
我不需要虚函数,它可以是派生的成员变量。
您可以使用static_assert
(编译时断言)使DerivedA<3>
(其中3 < 2
不满足条件)编译失败(如果您喜欢的话):
template <int parameter>
class DerivedA : public Base<parameter>
{
static_assert(parameter < 2, "Parameter for DerivedA is too large!");
// ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// condition message in case of error
public:
};
这将给你一个很好的提示,如果你写DerivedA<3>
:
错误:静态断言失败:DerivedA参数太大!
你可以把2
变成constexpr
成员。constexpr
表示它在编译时是已知的,这是static_assert
所需要的:
template <int parameter>
class DerivedA : public Base<parameter>
{
static constexpr int maxParameter = 2;
static_assert(parameter < maxParameter, "Parameter for DerivedA is too large!");
public:
};
如果您不喜欢在每个派生类中都有这些代码,您可以将其移动到Base
,它现在接受两个参数:实际参数和最大值。它的缺点是错误消息不能包含派生类的名称,但我想这不是很重要:
template <int parameter, int maxParameter>
class Base
{
static_assert(parameter < maxParameter, "Parameter is too large!");
};
template <int parameter>
class DerivedA : public Base<parameter, 2>
{
};
如果您不喜欢Base
类的第二个模板参数(就像您的问题中添加的工厂代码中的问题一样),您可以将其移动到Base
构造函数。调用模板化的构造函数有点棘手,但可以借助模板类型推断和虚拟参数:
template <int parameter>
class Base
{
public:
template <int maxParameter>
Base(std::integral_constant<int, maxParameter>) {
static_assert(parameter < maxParameter, "Parameter is too large!");
}
};
template <int parameter>
class DerivedA : public Base<parameter>
{
public:
DerivedA() : Base(std::integral_constant<int, 2>()) {
// ...
}
};
如果你不能在编译时使用static_assert
,因为你的派生类的getMaxParameter
的返回值还不知道,你可以使用工厂…
#include <iostream>
template <int parameter>
struct Base {
void verify () {
if (parameter > this->getMaxParameter())
std::cout << "Biggern";
else
std::cout << "Smallern";
}
virtual int getMaxParameter() = 0;
};
template <int parameter>
struct Derived : public Base<parameter> {
virtual int getMaxParameter() { return 0; }
};
template <int parameter>
Base<parameter> * make_and_verify () {
Base<parameter> * result = new Derived<parameter>;
result->verify();
return result;
}
int main() {
Base<0> * foo = make_and_verify<0>();
Base<1> * bar = make_and_verify<1>();
return 0;
}
验证输出
类是在编译时作为模板实例化创建的。
如果要检查的值是constexpr,则最好使用static_assert
:
template <int parameter>
class DerivedA : public Base<parameter>
{
public:
static_assert(parameter < 2, "wrong template parameter value");
int getMaxParameter() { return 2; }
};
或者,假设您可以将getMaxParameter
设置为constexpr
:
template <int parameter>
class DerivedA : public Base<parameter>
{
public:
constexpr int getMaxParameter() { return 2; }
static_assert(parameter < getMaxParameter(), "wrong template parameter");
};
相关文章:
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 命名参数习惯用法和(抽象)基类
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 如何允许模板参数中的类类型,仅当它有两个基类时
- 为什么我需要在成员发起器列表中重复基类的模板参数?
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- C++17 使用驱动类常量作为基类构造函数的参数来初始化基类构造函数
- 根据参数数调用 mixin 基类的构造函数
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 在C++单元测试上下文中,抽象基类是否应将其他抽象基类作为函数参数
- C++ 如何使派生类自动获取基类参数
- 将派生类作为参数传递给方法,该方法是具有智能指针的基类
- 如何隐藏模板基类的参数类型
- 根据模板参数引用不同基类的函数
- 继承基构造函数,基类是模板参数 (MSVC)
- C++ 模板:重载时找不到基类类型参数方法
- 是否可以从构造函数自动推断基类模板参数?
- 如何在 C++ 中将参数传递给基类构造函数
- 如何使用 CRTP 创建具有基类的可选模板参数