vsoftco
vsoftco

Reputation: 56567

Default function parameter value visible in template but it shouldn't (gcc)

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.

Upvotes: 6

Views: 118

Answers (1)

Columbo
Columbo

Reputation: 60999

[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).

Upvotes: 1

Related Questions