我有一个像
这样的基类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&amp;的模板参数Derived不超过getMaxParameter()的返回值?
我可以做类似
的事情DerivedA() {
if (parameter > getMaxParameter())
//...
}
但我不想在每个派生类中写这个。我可以在Base做这样的事吗?我不能称之为纯虚函数,但还有其他方法吗?
我不需要虚拟功能,它可以是例如取而代之的是Derived的成员变量。
答案 0 :(得分:4)
您可以使用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
构造函数。调用模板化构造函数but possible with the help of template type deduction and a dummy parameter:
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>()) {
// ...
}
};
答案 1 :(得分:3)
如果在编译时无法使用static_assert
因为派生类的getMaxParameter
的返回值尚未知晓,则可以使用工厂...
#include <iostream>
template <int parameter>
struct Base {
void verify () {
if (parameter > this->getMaxParameter())
std::cout << "Bigger\n";
else
std::cout << "Smaller\n";
}
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;
}
答案 2 :(得分:0)
该类在编译时创建为模板实例化。
您可以做的最好的事情是static_assert
要检查的值是constexpr:
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");
};