2015-12-08 9 views
1

N4527 14.6 [temp.res]/P8Различие интерпретации не-зависимой конструкция между контекстом определения и конкретизацией точкой в ​​C++

Если гипотетическая конкретизация шаблона сразу после его определения будет быть плохо сформированным из-за конструкции, которая не зависит от параметра шаблона, программа плохо сформирована; диагностика не требуется. Если интерпретация такой конструкции в гипотетическом экземпляре отличается от интерпретации соответствующей конструкции в любом фактическом экземпляре шаблона, программа плохо сформирована; диагностика не требуется. [Примечание: Это может произойти в ситуациях, в том числе следующие:

(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 Differences between definition context and point of instantiation

Различные характеристики субъектов, упомянутых на не-зависимых ссылок в шаблоне может изменить между контекстом определения и точкой создания специализации этого шаблона. К ним относятся инициализация (которая влияет на то, может ли объект использоваться в постоянном выражении), аргументы функции и шаблона по умолчанию, а также полноту типов. Существует расхождение внедрения в отношении того, проверяются ли они в контексте определения или в момент создания экземпляра. Предположительно, необходимо правило, чтобы сделать его плохо сформированным, не требуется диагностика, если справедливость такой ссылки изменяется между двумя контекстами.

Можете ли вы показать мне больше примеров того, как характеристики не зависимых имен различаются между двумя контекстами? Как правило, приблизительно 8,2 и 8.3.1

+0

Эти примеры не о «Если интерпретация такой конструкции в гипотетическом экземпляра отличается от интерпретации соответствующей конструкции в какой-либо фактической конкретизации шаблона, программа плохо формируется, нет диагностики требуется », но не демонстрируют этого. Метки «f» будут одинаковыми. Однако я не могу придумать правильный пример, который включает аргумент функции по умолчанию. –

+1

О, разрешение перегрузки. Возможно. Например. с рекурсивным вызовом. –

+2

@ Cheersandhth.-Alf Легко построить один: 'void g (long); void g (int, int); template void f() {g (0); } void g (int, int = 0) {} 'Edit: двухфазный поиск может скрыть это, несмотря на это. –

ответ

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) перегрузки SFINAEs прочь , Реализация экземпляра в # 2 (который является точкой инстанцирования g<int>) вызовет void f<0, 0>(int), потому что к тому времени b является постоянным выражением, перегрузка (int) жизнеспособна и выигрывает разрешение перегрузки.

Clang and GCC will in fact call different fs with this code.