Это можно сделать отдельным фрагментом кода с использованием std :: max, как показано в последней строке, но это несколько дублирует код и делает его не элегантным, поскольку мне придется постоянно его модифицировать.строка, поскольку все классы наследуются от B.
Вместо этого я хотел бы получить хорошее масштабируемое решение.
К сожалению, я не знаю способа автоматически узнать все производные типы (я нене думаю, что это возможно) поэтому я боюсь, что вам нужно «постоянно изменять эту строку, так как все больше классов наследуют форму B
».
В ответе LogicStuff вы видите элегантный способ упростить эту строку, и я также помню,существуют версия std::max()
, которая получает std::initializer_list
(constexpr
начиная с C ++ 14), поэтому вы также можете писать (но способ 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
struct, который наследуется от B
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
, если вы изменяете ваши Dx
классы для наследования B
, проходящего через C<Dx>
(таким образом, используя 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
}