Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 207
vsoftco Avatar asked Nov 12 '15 14:11

vsoftco


Video Answer


1 Answers

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

like image 122
Columbo Avatar answered Oct 22 '22 22:10

Columbo