When does overload resolution of non-dependent name take place, in definition context or point of instantiation?
Asked Answered
C

2

4

3.4 [basic.lookup]/p1

Overload resolution (13.3) takes place after name lookup has succeeded.

void g(long);

void g(int, int);

template<class T> void f() { g(0); }

void g(int, int = 0) {}

int main(){
    f<int>();
}

gcc compiles succeed, clang faild.

When does overload resolution of non-dependent name take place, in definition context or point of instantiation? Or both are right?

Clubman answered 8/12, 2015 at 11:30 Comment(0)
U
2

In both context.

[temp.res] 14.6\8

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.

[temp.nondep] 14.6.3\1

Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.

So both compilers are right.

Unfrequented answered 8/12, 2015 at 13:37 Comment(14)
According to 14.6\8 the example code is ill-formed, no diagnostic is required. But my question is valid, is there words in standard said about it? Both context are right?Clubman
The template has different interpretations depending on context. So that is an ill-formed template, but GCC allows you to use it, even it is... dangerous!Unfrequented
Which version of the standard are you quoting? No such wording in my copies of the drafts.Milliliter
@Eugene Zavidovsky I get it. Overload resolution takes place in both contexts, and the result must be same, if not, the program is ill-formed; no diagnostic is required.Clubman
@n.m. You can find them in n4527.Clubman
Yeah, and there is another rule for it, see [temp.point] 14.6.4.1\8Unfrequented
Yep, looks like a new wording in C++1xyzwhatever. A note below even explicitly addresses the case of default arguments. I wonder how the example in 14.6.3 is still valid when this wording is in effect, and why gcc in -std=c++11 mode does what it does.Milliliter
@n.m. I think, the example is like a reminder for brevity. If there was not h++ there, the program would be well-formed. But then it would be ill-formed, if there would be actual (explicit or implicit) instantiation for Z<T>::f(). But the implementation is not required to provide a diagnostic anyway...Unfrequented
The example is unchanged since C++11 or possibly before. It did make perfect sense before the wording in question was inserted. Now it's dubious at best. Is the "calls g(double)" remark still valid? Should it be replaced with "ill-formed"? The example is not intended to be a complete program, each line illustrates different aspects of the standard, and is "valid" or "invalid" independently of other lines, so h++ is irrelevant here.Milliliter
This is CWG 1950, cc @n.m. This wording is a result of an existing implementation variance. n.m.: That the example now seems invalid seems to be either an oversight or an unintended consequence, so why don't ask this on std-discussion?Astrix
@Astrix Looks like an unintended consequence to me. Not a member there, for a number of reasons.Milliliter
@Astrix Unless the intention is to dispose of the two-phase lookup entirely. I could understand that.Milliliter
@n.m. Not sure what you mean with "not a member there". If you don't want to post a question there, I'll do it later. (It's a fancy GUI on top of an old-fashioned mailing list, so membership is not required for posting or even subscribing.)Astrix
The more interesting question is when the name isn’t dependent (e.g., because it’s qualified) but an argument is type-dependent.Parable
E
0

If my understanding of the lookup rules are correct, then since g() is a non-dependent name, the overload set won't be added to in phase 2. Therefore the only choice for g(0) at the point of definition is g(long), and Clang is correct.

I would certainly naively expect only g(long) to be considered given the ordering of the definitions, but then again the C++ standard isn't always intuitive when templates are involved...

Esmerolda answered 8/12, 2015 at 12:20 Comment(1)
GCC is correct too, the program is ill-formed because of 14.6\8 - different interpretations. But the rule does not require diagnostic.Unfrequented

© 2022 - 2024 — McMap. All rights reserved.