c++language-lawyerlinkageargument-dependent-lookupdependent-name

Argument-dependent lookup of dependent names


This description on cppreference.com says that

The lookup of a dependent name used in a template is postponed until the template arguments are known, at which time [...] ADL examines function declarations with external linkage that are visible from either the template definition context or the template instantiation context.

Contrary to this the following code snippet compiles fine with three compilers (MSVC, clang, gcc):

template <class T>
void CallFoo ()
{
    Foo (T ());
}


class Apple {};


int main ()
{
    CallFoo<Apple> ();
}


static void Foo (Apple)
{
}

Foo is a dependent name in CallFoo: it depends on template argument T. But the function Foo is found by the compiler despite violating two of the above quoted rules.

It is unlikely, that all three compilers have a bug. I might have misunderstood something. Could you elaborate on this?


Solution

  • In C++03, members of anonymous namespaces could have external linkage despite being unnameable in other translation units. It was therefore thought permissible to preclude actual static functions from dependent ADL. In C++11, anonymous namespaces impose internal linkage, so the restriction became unreasonable. However, despite implementations adopting the new behavior and an issue being filed immediately in 2011 (as noted in the comments), the wording remained in two places until N4810 in March 2019.

    As for the placement of the function, this is an artifact of functions having multiple points of instantiation, including the end of any translation unit that instantiates them (with slight adjustments for modules in C++20); if instantiating the function template produces different results for different choices, the program is ill-formed, no diagnostic required (as also noted in the comments).