Различия в интерпретации независимой конструкции между контекстом определения и точкой создания в C++

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

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) Перегрузка является жизнеспособной и выигрывает разрешение перегрузки.

Clang и GCC на самом деле будут называть разные f с этим кодом.

Другие вопросы по тегам