Это похоже на проблему XY.Хотя я не рекомендую это (я рекомендую переосмыслить дизайн), я нашел (к лучшему или худшему) решение, основанное на шаблоне CRTP:
template <class D = void>
class Base
{
protected:
int data;
protected:
// This constructor should be called only in the derived classes
template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
Base(int d): data(d) {}
public:
// This constructor can be called wherever except a derived classes!
template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
Base(): data(0) { }
};
class Derived : public Base<Derived>
{
int mydata = 1;
public:
// The developer must not forget to initialize "data"
Derived() : Base(24) {}
// I want to get a compilation error there
//Derived() : Base() {} // (1) compilation error here
};
auto test()
{
Base b1{};
//Base b2{24}; // (2) compilation error here
Derived d{};
}
Конечно, есть проблемы с этим.Начнем с того, что ничто не мешает создать производный класс как class Derived : public Base<void>
.
. Если хотите, вы можете добавить общий базовый класс
class Base_l0
{
};
template <class D = void>
class Base_l1 : Base_l0
{
};
class Derived : public Base_l1<Derived>
{
};
.