c++language-lawyerc++20name-lookupunqualified-name

Why unqualified name lookup of a dependent name doesn't find a lambda declared between template declaration and instantiation?


The following program is incorrect,

inline constexpr auto makeFoo = [](auto const& x) {
    return getFoo(x);
};

inline constexpr auto getFoo = [](int const&) {
    return 1;
};

int bar() {
    return makeFoo(32);
}

and reversing the definitions of makeFoo and getFoo makes it correct.

I understand that based on "informal" understanding of the two-phases name lookup:


Can anybody guide me to the pieces of the standard draft that "mirror" the above explanation?

I suppose [basic.lookup.unqual] and [temp.dep.res] possibly contain all it's needed to explain the case, but I can't quite stitch the pieces together.


Solution

  • What argument-dependent lookup does is:

    1. Determine a set of associated entities ([basic.lookup.argdep]/3)
    2. Determine a set of associated namespaces of those entities (first sentence of [basic.lookup.argdep]/4)
    3. And then... the next sentence is:

    Argument-dependent lookup finds all declarations of functions and function templates that [...]

    Even without focusing on the details of where we're looking, argument-dependent lookup will only ever find declarations of functions and function templates. getFoo is neither a function or function template, it is an object — so it will never be found.

    So if you want getFoo to be found, it has to be found by regular lookup — which its declaration has to precede its call.