Здесь действуют несколько факторов.
A
является неполным
Во-первых, во всех объявлениях функций:
B<A> func2();
B<A>::C_type func3();
B<Other>::C_type func4();
A
является неполным типом:
[2003: 9.2/2]:
Класс считается полностью определенным типом объекта (3.9) (или полным типом) при закрытии }
класса .спецификатор .В пределах класса спецификация члена класс считается завершенным в теле функций, аргументах по умолчанию и конструкторе ctor-initializer (включая такие вещи во вложенных классах). В противном случае он считается неполным в своем собственном классе спецификация члена .
B<A>
требует создания экземпляра
func2
и func4
в порядке
Во-вторых, возвращаемый функцией тип может быть неполным.Это означает, что возвращаемые типы func2
и func4
хороши в том виде, в каком они есть.
[2003: 8.3.5/6]:
[..] Тип параметра или тип возвращаемого значения для функцииопределение не должно быть неполным типом класса (возможно, cv-квалифицированным), если определение функции не вложено в спецификацию члена для этого класса (включая определения во вложенных классах, определенных в классе).
func3
не в порядке
Однако в более сложном примере func3
для использования типа B<A>::C_type
необходимо заполнить B<A>
. *
И поэтому он также должен быть создан :
[2003: 14.7.1/1]:
Если специализация шаблона класса не была явно создана (14.7.2) или явно специализирована (14.7.3), специализация шаблона класса неявно создается, когда на специализацию ссылаются в контексте, который требует полностью определенного типа объекта или когда полнота типа класса влияет насемантика программы.[..]
Но поскольку B<A>
содержит член типа A
, а A
не является полным типом, а [8.3.5/6]
требует, чтобы это было, экземплярневерно, B<A>
остается неполным ... и программа не сформирована.
* Я еще не нашел цитаты, подтверждающей это, хотя это кажется очевидным.