Clang как обычно выдает очень полезное сообщение об ошибке, которое объясняет все:
error: missing 'typename' prior to dependent type name 'Base<D>::func'
Derived(Base<D>::func f) : Base<D>(f) { };
^~~~~~~~~~~~~
typename
Если зависимое имя является типом или шаблоном, оно должно быть устранено с помощью ключевого слова typename
или template
соответственно.
Это необходимо, потому что в определении Derived
компилятор не знает, какой тип будет использоваться вместо D
, и поэтому он не знает, каково будет фактическое определение Base<D>
из-за возможных специализаций.Вот почему любой идентификатор внутри Base<D>
зависит от типа D
.
Однако компилятору все еще нужно иметь возможность анализировать этот код, который он понимает лишь частично, поэтомувам нужно помочь, сказав, что идентификатор func
является не просто членом Base<D>
, но typename
, поскольку он определяет контекст, в котором этот идентификатор может использоваться.
На заметке: есть
предложение , чтобы избавиться от этого раздражающего правила для контекстов, где можно использовать только тип, например, ваш.