It is possible to do so in a separate chunk of code with the usage of std::max as shown in the last line, but it's some what duplicate code and unelegant, as I will have to continuously modify that line as more classes inherit from B.
I would like a nice scalable solution instead.
Unfortunately, I don't know a way to automatically know all derived types (I don't think it's possible) so I fear that you needs "to continuously modify that line as more classes inherit form B".
In LogicStuff's answer you see an elegant way to simplify that line and I also remember that exist the std::max() version that receive a std::initializer_list (constexpr starting from C++14) so you can also write (but the biggest_size_v way is better, IMHO)
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)});
avoiding the multiple std::max() calls.
A little off topic, I suppose, but I propose you a semi-automatic way to check, compile-time, that B::BIGGEST_TYPE_SIZE is bigger (or equal) to the sizeof() of all derived types (all instantiated derived type, at least).
If you modify B adding a constructor with a static_assert() in it (or SFINAE enabled, if you prefer)
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, "!" ); }
};
and add a template C struct that inherit from B
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
if you modify your Dx classes to inheriting B passing through C<Dx> (so using 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; };
you auto-magically enable the compile-time check inside B constructor.
So if you add, by example, the following D4 class
struct D4 : public C<D4>
{ int a[42]; };
and forget to modify the BIGGEST_TYPE_SIZE initialization adding sizeof(D4) in the list, declaring a D4 object you get a compilation error
D4 d4; // compilation error
The following is a full compiling example
#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
}