6

Consider the code below:

#include <utility>

void f(int, int);
void g(int, int);

struct functor
{
    template<typename... T>
    void operator()(T&&... params)
    {
        return f(std::forward<T>(params)...);
    }
};

int main()
{
    functor()(1); // can use the default value here, why?!
    // g(1); // error here as expected, too few arguments
}

void f(int a, int b = 42) {}

void g(int a, int b = 24) {}

This is a thin wrapper around a function call. However, inside functor::operator(), f doesn't have its default value for the second parameter known (it is visible only after main, in the definition), so the code should not compile. g++5.2 compiles it successfully though, but clang++ spits out the expected message that one expects for compilers that perform the two-phase name lookup correctly:

error: call to function 'f' that is neither visible in the template definition nor found by argument-dependent lookup return f(std::forward(params)...);

Is this a gcc bug or I am missing something here? I.e., is the point of instantiation after the definition of f below main()? But even in this case, it shouldn't work, as at the second phase the function can only be found via ADL, which is not the case here.

4
  • 2
    End of translation unit is also a valid point of instantiation. Commented Nov 12, 2015 at 14:27
  • Yes, but it still shouldn't work, since at the second phase only ADL is performed. Commented Nov 12, 2015 at 14:27
  • If instantiates at end of file, definition of f with default parameter is visible... Wonder if the program is not ill-formed... Commented Nov 12, 2015 at 14:30
  • @Jarod42 Ohh I see, yes I think you're right, since f itself was found before, and now the definition with the default param is visible. The definition is not other function, it's just the same function. Commented Nov 12, 2015 at 14:32

1 Answer 1

1

[temp.dep.candidate]:

For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:

  • For the part of the lookup using unqualified name lookup ([basic.lookup.unqual]), only function declarations from the template definition context are found.

  • For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.

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.

Note that ADL is not even working here, as the involved types are fundamental (their set of associated namespaces is empty).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.