Это запрещено как текстом стандарта, так и несколькими основными реализациями, как отмечено в комментариях, но по совершенно не связанным причинам.
Во-первых, причина «по книге»: точка инстанцирования A<C>, согласно стандарту, находится непосредственно перед определениемB , а точка инстанцирования std::is_default_constructible<C>находится непосредственно перед этим:
Для специализации шаблона класса, [...] если специализация создается неявно, потому что на нее ссылаются из другой специализации шаблона, если контекст, на который ссылается специализация, зависит от параметра шаблона, и если специализация не была создана предыдущая до создания экземпляра вмещающего шаблона точка создания экземпляра находится непосредственно перед точкой создания вмещающего шаблона. В противном случае точка создания такой специализации непосредственно предшествует объявлению или определению области пространства имен, относящемуся к специализации.
Поскольку Cв этот момент он явно неполон, поведение создания экземпляров std::is_default_constructible<C>не определено. Однако, смотрите основную проблему 287 , которая изменит это правило.
На самом деле это связано с NSDMI.
- NSDMI являются странными, потому что они получают задержанный анализ - или, в стандартном языке, они представляют собой «полный классовый контекст».
- Таким образом,
= 0в принципе это может относиться к вещам, которые Bеще не объявлены, поэтому реализация не может попытаться проанализировать их до тех пор, пока они не закончатся B.
- Завершение класса требует неявного объявления специальных функций-членов, в частности конструктора по умолчанию, так как
Cконструктор не объявлен.
- Части этого объявления (constexpr-ness, noexcept-ness) зависят от свойств NSDMI.
- Таким образом, если компилятор не может проанализировать NSDMI, он не может завершить класс.
- В результате, в момент, когда он создает экземпляр
A<C>, он думает, что Cон неполон.
Вся эта область, имеющая дело с областями с анализом с задержкой, крайне не указана, что сопровождается расхождением в реализации. Это может занять некоторое время, прежде чем он будет очищен.