Differences of the interpretation of a non-dependent construct between definition context and point of instantiation in c++

跟風遠走 提交于 2019-12-19 07:39:37

问题


N4527 14.6 [temp.res]/p8

If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required. If the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template, the program is ill-formed; no diagnostic is required. [ Note: This can happen in situations including the following:

(8.1) — a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or

(8.2) — an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or

(8.3) — constant expression evaluation (5.20) within the template instantiation uses

(8.3.1) — the value of a const object of integral or unscoped enumeration type or

(8.3.2) — the value of a constexpr object or

(8.3.3) — the value of a reference or

(8.3.4) — the definition of a constexpr function,

and that entity was not defined when the template was defined, or

So, are these codes ill-formed?

code 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?
}

code 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;

And Issue1850 Differences between definition context and point of instantiation

Various characteristics of entities referred to by a non-dependent reference in a template can change between the definition context and the point of instantiation of a specialization of that template. These include initialization (which affects whether an object can be used in a constant expression), function and template default arguments, and the completeness of types. There is implementation divergence as to whether these are checked in the definition context or at the point of instantiation. Presumably a rule is needed to make it ill-formed, no diagnostic required, if the validity of such a reference changes between the two contexts.

Can you show me more examples about how are characteristics of non-dependent names different between the two contexts? Typically about 8.2 and 8.3.1


回答1:


Here's an example:

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

A hypothetical instantiation at #1 will call void f<0, b>(long), because b isn't a constant expression at that point, so the (int) overload SFINAEs away. An instantiation at #2 (which is a point of instantiation of g<int>) will call void f<0, 0>(int), because by then b is a constant expression, the (int) overload is viable and wins overload resolution.

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



来源:https://stackoverflow.com/questions/34149992/differences-of-the-interpretation-of-a-non-dependent-construct-between-definitio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!