Ответ: вы не можете сделать это с CRTP в C ++.Что происходит, когда создается экземпляр Base<Foo>
, Foo::bsize
еще не существует.Это происходит потому, что это происходит, когда компилятор видит Base<Foo>
в классе Foo
, который находится перед вашим {
.Это не совсем так просто, но это общая идея.
Есть обходной путь, чтобы сделать то, что вы хотите здесь, то есть объединить всю необходимую информацию в классе, затемпредоставить его в качестве параметра шаблона.Я не знаю названия этого паттерна (я видел «класс багажа», но это кажется уничижительным), но вы можете найти примеры этого в стандартной библиотеке, такой как std::char_traits
.
class FooTraits {
constexpr static size_t bsize = 2;
};
template <class Traits = FooTraits>
class BasicFoo {
protected:
std::bitset<Traits::bsize> data_;
};
Черты довольно гибкие - вы можете просто вставить функцию static constexpr
в свой FooTraits
, чтобы вычислить все, что вам нужно.В вашем случае производный класс будет передавать специфичную для производного типа версию FooTraits
аргументу шаблона Traits
, равному BasicFoo
.
Стоит отметить, что ваш milage может отличаться.Несмотря на гибкость, проблема с чертами заключается в том, что кто-то, желающий реализовать концепцию FooTraits
, должен убедиться, что он реализует все, что нужно BasicFoo
, иначе он получит ужасную ошибку компиляции (в C ++ 20 это помогаетчерез понятия ).Без тщательного обдумывания черты могут стать местом свалки, что делает реализацию альтернативы FooTraits
еще сложнее.