Как получить размер или тип наследника из конструктора базового класса?

Есть множество структур, в конструкторе которых берётся их размер (через sizeof) и выполняются определённые действия. В каждой структуре код приходится копипастить. Очевидное решение этой проблемы, сделать базовый класс от которого наследовать все эти структуры и вынести код туда. Но как в конструкторе базового класса получить тип, конструктор которого был вызван на самом деле?

struct Base {
  public:
   Base() {
      cout << sizeof( *this ) << endl;  // Как тут понять что на самом деле это часть конструктора Foo?
   };
   uint8_t base_1 = 0;
};

struct Foo : public Base {
   uint8_t foo_1 = 0;
};

int main() {
   Foo foo; // В консоль будет выведено '1'.
   return 0;
}

Как сделать тоже самое на этапе компиляции?

constexpr size_t kFooExpectedSize = 2;
struct Base {
  public:
   Base() { 
      static_assert( sizeof( *this ) == kExpectedSize, "Wrong size" ); // Следующий уровень сложности =) 
   };
   uint8_t base_1 = 0;
};

struct Foo : public Base {
   uint8_t foo_1 = 0;
};

int main() {
   Foo foo;
   return 0;
}

Ответы (1 шт):

Автор решения: Chorkov

Варианты:

Шаблонный подход (в духе CRTP):

template<typename FinalClass>
struct Base {
  public:
   Base() {
      cout << sizeof( FinalClass ) << endl; 
   };
   uint8_t base_1 = 0;
};
struct Foo : public Base<Foo> {
   uint8_t foo_1 = 0;
};    

Шаблонный конструктор:

struct Base {
  public:
   template<typename FinalClass>
   Base(FinalClass*) {
      cout << sizeof( FinalClass ) << endl;  // Как тут понять что на самом деле это часть конструктора Foo?
   };
   uint8_t base_1 = 0;
};

struct Foo : public Base {
    Foo() : Base(this) {}
    template<typename FinalClass> Foo(FinalClass*ptr) : Base(ptr) {} // если предполагается дальнейшее наследование
   uint8_t foo_1 = 0;
};

Конструктор с параметром (если от финального класса нужен только его размер):

struct Base {
  public:

   Base(size_t final_size) {
      cout << final_size << endl;  // Как тут понять что на самом деле это часть конструктора Foo?
   };
   uint8_t base_1 = 0;
};

struct Foo : public Base {
    Foo(size_t final_size = sizeof(Foo)) : Base(final_size) {}
   uint8_t foo_1 = 0;
};
→ Ссылка