Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do function objects affect overload resolution?

Are function objects treated differently from regular functions during overload resolution? If so, how?

I have run into the following case where replacing a function with an equivalently-callable function object changed the meaning of the code:

#include <iostream>

namespace N
{
    enum E { A, B };

    void bar(E mode) { std::cout << "N::bar\n"; }
}

template <typename... Args>
void bar(Args&&... args) { std::cout << "global bar\n"; }

int main()
{
    bar(N::A);
}

Here the output is "N::bar". So far, so good: N::bar is being found by ADL, both N::bar and the global bar are exact matches, and N::bar is preferred because it's not a template.

But if I change the global bar to be a function object, like so:

#include <iostream>

namespace N
{
    enum E { A, B };

    void bar(E mode) { std::cout << "N::bar\n"; }
}

struct S
{
    template <typename... Args>
    void operator()(Args&&... args) { std::cout << "global bar\n"; }
};
S bar;

int main()
{
    bar(N::A);
}

The output is now "global bar". Why the difference?

like image 997
HighCommander4 Avatar asked Aug 29 '12 03:08

HighCommander4


People also ask

What happens when you overload functions?

Using the function overloading concept, we can develop more than one function with the same name, but the arguments passed should be of different types. Function overloading executes the program faster. Function overloading is used for code reusability and to save memory.

What is function overloading Why is it necessary to overload function?

Function overloading shows the behavior of polymorphism that allows us to get different behavior, although there will be some link using the same name of the function. Function overloading speeds up the execution of the program. Function overloading is used for code reusability and also to save memory.

What is overload resolution?

The process of selecting the most appropriate overloaded function or operator is called overload resolution. Suppose that f is an overloaded function name. When you call the overloaded function f() , the compiler creates a set of candidate functions.

What are the requirements to overload a function?

To overload functions, they must have a different= set of parameters, i.e., either have parameters of different data types or a different number of parameters in the function definition. Functions with different return types and identical parameters can not be overloaded.


1 Answers

The important bit here is that ADL only kicks in if lookup determines that the name is a function in the function call. In the second case, bar is found to be an object and not a function, so the expression bar(N::A) is not a function call, but the application of operator() to the object bar. Because it is not a function call, ADL does not kick in and N::bar is not considered.

3.4.1/3

The lookup for an unqualified name used as the postfix-expression of a function call is described in 3.4.2. [ Note: For purposes of determining (during parsing) whether an expression is a postfix-expression for a func- tion call, the usual name lookup rules apply. The rules in 3.4.2 [ADL] have no effect on the syntactic interpretation of an expression.

Another way to look at it is to notice that ADL will add new functions to the set of overloaded functions, but in the second example there is no such set: lookup finds an object and a member of the object is called.

like image 150
David Rodríguez - dribeas Avatar answered Oct 07 '22 16:10

David Rodríguez - dribeas