N4527 14,6 [temp.res] / p8
Если гипотетическая реализация шаблона немедленно
следование его определению будет некорректным из-за конструкции, которая не зависит от параметра шаблона,
программа плохо сформирована; Диагностика не требуется. Если интерпретация такой конструкции в
гипотетическая реализация отличается от интерпретации соответствующей конструкции в любой фактической
создание шаблона, программа плохо сформирована; Диагностика не требуется. [Примечание: это может произойти
в ситуациях, включающих следующее:(8.1) — тип, используемый в независимом имени, является неполным в момент, когда шаблон определен, но
завершить в тот момент, когда выполняется создание экземпляра, или(8.2) — экземпляр использует аргумент по умолчанию или аргумент шаблона по умолчанию, который не был определен в
точка, в которой был определен шаблон, или же(8.3) — оценка константного выражения (5.20) в рамках использования шаблона
(8.3.1) — значение константного объекта целочисленного или незаданного типа перечисления или же
(8.3.2) — значение объекта constexpr или
(8.3.3) — значение ссылки или
(8.3.4) — определение функции constexpr,
и этот объект не был определен при определении шаблона, или
Итак, эти коды плохо сформированы?
код 1:
extern double b;
template<class T>
void f(T=b){}
void g(){
f<double>();//ill-formed or not?
}
double b = 0;
void h(){
f<double>();//ill-formed or not?
}
код 2:
//translation 1
extern double b;
template<class T>
void f(T=b){}
void g(){
f<double>();//ill-formed or not?
}
//translation 2
double b = 0;
А также Issue1850 Различия между контекстом определения и точкой создания
Различные характеристики сущностей, на которые ссылается независимая ссылка в шаблоне, могут изменяться между контекстом определения и точкой реализации специализации этого шаблона.. К ним относятся инициализация (которая влияет на возможность использования объекта в константном выражении), аргументы функций и шаблонов по умолчанию и полнота типов. Существует расхождение в реализации того, проверяются ли они в контексте определения или в момент создания экземпляра. Предположительно, для того, чтобы сделать его плохо сформированным, требуется правило, не требующее диагностики, если достоверность такой ссылки изменяется между двумя контекстами.
Можете ли вы показать мне больше примеров того, как характеристики не зависимых имен различаются между двумя контекстами? Обычно о 8.2 и 8.3.1
Вот пример:
extern const int b;
template<int, int>
void f(int);
template<int, const int &>
void f(long);
template<class>
void g() {
f<0, b>(0);
}
// #1
extern const int b = 0;int main(){
g<int>();
}
// #2
Гипотетический экземпляр в # 1 вызовет void f<0, b>(long)
, так как b
не является постоянным выражением в этой точке, поэтому (int)
перегрузить сфины прочь. Инстанциация в # 2 (который является точкой инстанцирования g<int>
) позвоню void f<0, 0>(int)
потому что к тому времени b
является постоянным выражением, (int)
Перегрузка является жизнеспособной и выигрывает разрешение перегрузки.
Других решений пока нет …