Here is a minimalist example of a very strange overload resolution from a template context:
#include <iostream>
// Types //
struct I { int v; };
template <class T>
struct D { T t; };
// Functions //
// Overload 1
template <class T>
I f(T) { return {1}; }
// Template indirection that calls f(T)
template <class T>
I g(D<T>) { return f(T{}); }
// Non template indirection that calls f(T)
I h(D<I>) { return f(I{}); }
int main() {
std::cout
<< f(I{}).v // f(I{}) overload called directly
<< "\n" // => overload 1 called
<< h(D<I>{}).v // f(I{}) called though non-template
<< "\n" // => overload 1 called
<< g(D<I>{}).v // f(I{}) called though template
<< "\n"; // => overload 2 actually called ???
}
// Overload 2
// Should not be reachable as declared after all f(...) calls.
// If was a candidate, would be chosen over 1.
I f(I) { return {2}; }
This seem to be related to ADL because if I
is placed in a namespace "overload 1" is always called.
I know that ADL is performed as if the call was made from the template instantiation point (main
).
For a dependent name used in a template definition, the lookup is postponed until the template arguments are known, at which time ADL examines function declarations with external linkage (until C++11) that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarations with external linkage (until C++11) that are visible from the template definition context. http://en.cppreference.com/w/cpp/language/unqualified_lookup#Template_definition
But here "Overload 2" is declared AFTER main
! main
being the instanciation point of g
and f
, I assumed only function declared before main
would be overload candidates.
Note that this behaviour is related to g
being template as h
(g
's equivalent not template function) calls "Overload 1".
How can "overload 2" -being declared after main
- ever be called ?
This behaviour has been reproduced with clang++ (3.8.1) and g++ (6.2.1).