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

1

7

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

Cleancut answered 8/12, 2015 at 7:10 Comment(4)
These examples are about "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.", but do not demonstrate this. The instantations of f will be the same. However, I can't think of a proper example that involves a defaulted function argument.Buggy
Oh, overload resolution. Possibly. E.g. with recursive call.Buggy
@Cheersandhth.-Alf Easy to construct one: void g(long); void g(int, int); template<class T> void f() { g(0); } void g(int, int = 0) { } Edit: two-phase lookup might foil this one regardless, though.Zonazonal
@stackcpp: 8.2 is a non-normative example of "If the interpretation...".Buggy
Z
7

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.

Zonazonal answered 9/12, 2015 at 4:38 Comment(1)
Is g() here a dependent name?Toll

© 2022 - 2024 — McMap. All rights reserved.