可以使用 std::max 在单独的代码块中执行此操作,如最后一行所示,但这是一些重复的代码和不优雅的代码,因为我将不得不不断修改该行类继承自 B。
我想要一个很好的可扩展解决方案。
不幸的是,我不知道自动知道所有派生类型的方法(我认为这不可能)所以我担心你需要“随着更多类继承B 形式而不断修改该行”。
在 LogicStuff 的回答中,您看到了一种简化该行的优雅方法,我还记得存在接收 std::initializer_list(constexpr 从 C++14 开始)的 std::max() 版本,因此您也可以编写(但是biggest_size_v 方式更好,恕我直言)
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)});
避免多次std::max() 调用。
我想有点离题,但我建议您使用一种半自动的方式来检查编译时 B::BIGGEST_TYPE_SIZE 是否大于(或等于)所有派生类型的 sizeof()(所有实例化派生至少输入)。
如果您修改 B 添加带有 static_assert() 的构造函数(或启用 SFINAE,如果您愿意)
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
并添加一个模板 C 结构,该结构继承自 B
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
如果您将 Dx 类修改为通过 C<Dx> 继承 B(因此使用 CRTP)
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
您在 B 构造函数中自动启用编译时检查。
因此,例如,如果您添加以下 D4 类
struct D4 : public C<D4>
{ int a[42]; };
忘记修改BIGGEST_TYPE_SIZE初始化在列表中添加sizeof(D4),声明一个D4对象你得到一个编译错误
D4 d4; // compilation error
以下是完整的编译示例
#include <vector>
#include <iostream>
#include <algorithm>
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
struct D4 : public C<D4>
{ int a[42]; };
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)}); // <-- sizeof(D4) forgotten !!!
int main ()
{
D1 d1;
D2 d2;
D3 d3;
// D4 d4; compilation error
}