Consider the following code, in which the location of the overloads of f
causes some non-intuitive behaviour. The code compiles with no warnings in both Clang 3.4.1 and gcc 4.8.
template<typename T>
struct A
{
static const int value = sizeof(f(T()));
};
struct B
{
};
struct D : B
{
};
char f(B);
// instantiates A<D>, unqualified name lookup finds f(B) via ADL
static_assert(A<D>::value == sizeof(f(B())), ""); // passes
long f(D); // but wait, f(D) would be a better match!
// A<D> is already instantiated, f(D) is not found
static_assert(A<D>::value == sizeof(f(B())), ""); // passes
The C++11 standard suggests that the above code invokes undefined behaviour:
[temp.dep.candidate]
For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules except that:
- For the part of the lookup using unqualified name lookup or qualified name lookup, only function declarations from the template definition context are found.
- For the part of the lookup using associated namespaces, only function declarations found in either the template definition context or the template instantiation context are found.
If the function name is an unqualified-id and 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.
Does the above code invoke this specific undefined behaviour? Could a high-quality implementation be expected to report a warning?