Как получить размер или тип наследника из конструктора базового класса?
Есть множество структур, в конструкторе которых берётся их размер (через 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;
};