6

When a function body is instantiated, dependent function call overload resolution should find the best match in associated namespace through ADL, otherwise the behavior is undefined, [temp.dep.candidate]§1

If the call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behavior.

For exemple:

struct A {
    friend void f(A a){};
};

struct B : A {};

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

void h(B b){
    g(b);//undefined behavior (UB)
}
 //TU2.cpp
 //...
void f(B){}

I have 2 doubts about which functions could be one of all the function declarations with external linkage introduced in those namespaces

Question 1

Does inline friend function considered to be introduced in the enclosing namespace?

Exemple:

struct A {
    friend void f(A a){};
};

struct B : A {};

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

void h(B b){
    g(b);//undefined behavior ??
}
//TU2.cpp
//....
struct C {
   operator B();
   friend void f(B){}
   };

Question 2

Could function template specialization also trigger this undefined behavior? (Potentialy instantiated or instantiated function template specialization)

Exemple:

struct A {
    friend void f(A a){};
};

struct B : A {};

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

void h(B b){
    g(b);//undefined behavior ??
}
//TU2.cpp
//...
template <class T> void f(T){}

// optionaly also with:
// template void f(B);
Oliv
  • 17,610
  • 1
  • 29
  • 72
  • 3
    @YunfeiChen Undefined behavior does not mean that the output is unexpected. It simply means that it's undefined. You can very well experience output that would appear to be from a well-formed program. The only way to be sure if a program is well-formed is by referencing the standard. Hence the language-lawyer tag. – David G Jul 26 '20 at 20:41
  • @YunfeiChen "get an IDE and run it, if it outputs something that does not make sense it is undefined" - Ehh, *No*. You cannot test for UB after the fact, you have to write your code so it avoids it *in the first place*. If your code contains UB it means the *entire program* is meaningless and the compiler is allowed to generate *anything*. At runtime it's too late. The compiler will have already exploited the UB and your program has no well defined behaviour. – Jesper Juhl Jul 26 '20 at 20:45
  • 3
    @YunfeiChen Consistent output still wouldn't guarantee you that the program is well-formed. The program could have a consistently _unexpected_ output which could be caused by UB. The only way to be sure is to refer to the standard. – David G Jul 26 '20 at 20:58
  • 1
    _"had the lookup within the associated namespaces considered all the function declarations"_ indeed could be read as (for friends) _"had the unqualified lookup considered names «visible» only to ADL"_. I think P1787 should solve this by removing [namespace.memdef] and, in general, replacing "not found by lookup" with "bind". – Language Lawyer Jul 26 '20 at 23:54
  • @LanguageLawyer Indeed for the friend case above, P1787 makes it clear that it is UB: "Friend declarations may introduce functions or classes that belong to the nearest enclosing namespace or block scope, but they do not introduce new bind". What do you think about the template case? Could an instantiation of a function template be an introduction of a function into a namespace? – Oliv Jul 27 '20 at 10:43
  • @LanguageLawyer And I wonder what this rule is about: does it aims at easing implementation of template instantiation at link-time? – Oliv Jul 27 '20 at 10:44
  • @DavisHerring Considering P1787, are [declared specialization](https://timsong-cpp.github.io/cppwp/n4861/temp.spec#temp.inst-1) of function template introduced in the namespace where the template is declared? – Oliv Jul 27 '20 at 12:04
  • _Indeed for the friend case above, P1787 makes it clear that it is UB_ I'm not so sure. To me, P1787 reads as that it makes it clear that the paragraph should not be read as I wrote in my first comment. It is a funny reading, but I think not intended one. – Language Lawyer Jul 29 '20 at 15:36
  • @LanguageLawyer It's getting confusing. I don't know if "I'm not so sure" applies to "makes it clear" or "it is UB". Do you think the standard specification intend is to give the friend case above well defined behavior? – Oliv Jul 29 '20 at 16:01
  • Ah... Now I think P1787 doesn't change anything here. But I still think that the paragraph is not intended to be read as "if lookup considered names visible only to ADL". I'll look closer later. Maybe. – Language Lawyer Jul 29 '20 at 16:36
  • @Oliv: (Sorry I didn’t notice this comment via your link elsewhere; @ doesn’t work on people who haven’t contributed to the discussion.) All specializations belong to the same scope as the primary template; it would be very strange to consider them here, partly because they might not be deducible. – Davis Herring Oct 15 '20 at 16:00

0 Answers0