Це заборонено як текстом стандарту, так і кількома основними реалізаціями, як зазначено в коментарях, але з абсолютно незв'язаних причин.
По-перше, причина "за книгою": точка моменту описується 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це неповно.
Вся ця область, що стосується регіонів із затримкою, проаналізованими, надзвичайно визначена, із супутніми розбіжностями щодо впровадження. Це може зайняти деякий час, перш ніж воно очиститься.