Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overload on std::function signature in C++

I know this question has been asked before, but despite being a fairly experienced coder I don't understand the answers and see no way to respond to these previous questions to ask for clarification. There is no "reply" link or anything. Besides, those questions were quite old. So, I'm asking the question afresh.

I have a class, in which I am overloading the += operator. I want one overload to take a bare function pointer, and the other to take a std::function:

void operator+=(void (*handler)());
void operator+=(function<void (void *, T)> handler);

Usage:

MyClass a;
a += [](){ DoSomething(); };
a += [](void *x, T y){ DoSomething(); };

Unfortunately, the code does not compile because the compiler cannot determine that the second overload is unsuitable for the first += call.

How do I define my operator+= member functions to correct this problem? I don't want to change how the operators are used (e.g. by using an explicit cast). I want them to work as demonstrated above.

In addition, it would be handy to have the following overload as well:

void operator+=(function<void()> handler);

But again, I can't overload based on the signature of the function<> template.

See this thread for further examples: Isn't the template argument (the signature) of std::function part of its type? (I tried implementing the various solutions mentioned in that thread, and none of them would compile)

I've been programming for many years in a number of languages, but my C++ skills are a little rusty.

like image 373
Sod Almighty Avatar asked Dec 10 '12 23:12

Sod Almighty


People also ask

What would the signature in function overloading function?

Function Signature A function's signature includes the function's name and the number, order and type of its formal parameters. Two overloaded functions must not have the same signature. The return value is not part of a function's signature.

What is C++ function signature?

C++ Reference. Programming Terms. Function Signatures. A function signature consists of the function prototype. What it tells you is the general information about a function, its name, parameters, what scope it is in, and other miscellaneous information.

What is the signature of function?

A function signature (or type signature, or method signature) defines input and output of functions or methods. A signature can include: parameters and their types. a return value and type. exceptions that might be thrown or passed back.


1 Answers

Following code works well with g++ 4.7.2:

#include <functional>
#include <iostream>

template <typename T>
typename std::enable_if<std::is_convertible<T, void(*)()>::value>::type
foo(T&&)
{
    std::cout << "foo(void(*)())" << std::endl;
}

void foo(std::function<void(void*,int)>)
{
    std::cout << "foo(std::function<void(void*,int)>)" << std::endl;
}

int main()
{
    foo([]{});
    foo([](void*,int){});
}

The problem is caused by the constructor of std::function, which is declared as template <class F> function(F);. That constructor accepts everything as its argument. If that argument doesn't have an appropriate operator(), an error is generated during the instantiation of the constructor.

Unfortunately the overload resolution process doesn't require any template functions to be instantiated, so the compiler believes everything can be converted to any std::function type.

like image 78
hpsMouse Avatar answered Oct 19 '22 03:10

hpsMouse