Я пытаюсь создать общий код, который вызовет ошибку компиляции, если B не является предком D. Что я придумал:
template<typename B, typename D>
struct assert_base_of {
enum {value = sizeof(B::D)};
}
Это не работает. Когда я «вызываю» это так:
assert_base_of<A2,A1>::value;
Я получаю следующую ошибку (g++ 4.8.2):
main.cpp:16:22: error: ‘D’ is not a member of ‘A2’
Похоже, параметр шаблона D не заменяется на A1. Может ли кто-нибудь объяснить и предложить решение, пожалуйста?
static_assert (std::is_base_of<B, D>::value, "B must be a base of D")
? - person Alexandre C.   schedule 20.06.2015B::D
интерпретируется как член (а не тип), потому чтоB
здесь зависим. В любом случае, вы не можете получить такой базовый класс — вам нужно привести указатель отD
кB
, чтобы проверить, наследует лиD
B
. См. ответ @Veritas о том, как реализоватьis_base_of
. - person Alexandre C.   schedule 20.06.2015B
зависимый означает, что он зависит от параметра шаблона (здесь это является параметром шаблона). Когда вы пишетеB::foo
,foo
всегда интерпретируется как имя членаB
, еслиB
является зависимым (это связано с тем, что компилятор дважды просматривает ваш шаблон, и в первом проходе он не знает, что в итоге будетB
) . Если вы хотите, чтобыfoo
называл тип, вы должны использоватьtypename B::foo
. Если вы хотите, чтобыfoo
назвал шаблон, вы должны использоватьtemplate B::foo
. - person Alexandre C.   schedule 20.06.2015sizeof(A::B)
без шаблона, - это внедренное имя классаB
вB
(typenameB
внедряется вB
, иA
наследует его -A::A
тоже существует как тип). Это темный угол C++, которого вам следует избегать, поскольку он ведет себя по-разному с шаблонами. См. stackoverflow.com /questions/7025054/ и связанные вопросы. Здесь важно то, чтоA::B
называет тип, а не элемент. - person Alexandre C.   schedule 20.06.2015