Ответ 1
Это то, что стандарт должен сказать (§20.9.5/6), с моим акцентом:
Учитывая следующий прототип функции:
template <class T> typename add_rvalue_reference<T>::type create();
условие предиката для типовой специализации
is_constructible<T, Args...>
должно выполняться тогда и только тогда, когда следующее определение переменной будет хорошо сформировано для некоторых изобретенных переменнаяt
:T t(create<Args>()...);
[Примечание: эти токены никогда не интерпретируются как функция декларация. -end note]
Проверка доступа выполняется, как если бы в контексте, не связанном с
t
и любой изArgs
. Только действительность непосредственного контекста рассматривается переменная инициализация. [Примечание: оценка инициализация может привести к побочным эффектам, таким как создание специализированные шаблоны классов и специализированные шаблоны функций, генерация неявно определенных функций и т.д. Такая сторона эффекты не находятся в "непосредственном контексте" и могут привести к программа плохо организована. -end note]
Утверждение завершается только при создании экземпляра шаблона. Однако, как выяснено в примечании, это утверждение не находится в непосредственном контексте рассматриваемого определения переменной и, таким образом, не влияет на его "действительность". Поэтому компиляторы могут считать это определение действительным и, следовательно, утверждают, что foo
действительно конструктивен из int
, даже если на самом деле попытка построить a foo
из int
приводит к плохо сформированной программе.
Обратите внимание, что компиляторам также разрешено вместо is_constructible
yield false просто отклонить исходную программу на основе этого утверждения, даже если это не так.