Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass an overloaded member-function as parameter?

Here is the problem I am facing: I have an overloaded function in a class, and I want to pass one of its overloads as a parameter. But when doing so, I get the following error :

"no suitable constructor exists to convert from <unknown-type> to std::function<...>"

Here's a code sample to illustrate that :

#include <functional>
#include <string>

class  Foo
{
private:
    int val1 , val2;
};    

class Bar
{
public:
    void function ( ) {
        //do stuff;
        Foo f;
        function ( f );
    }    
    void function ( const Foo& f ) {
        //do stuff
    }

private:
    //random attribute
    std::string str;    
};


void otherFunction ( std::function<void ( Bar& , const  Foo& ) > function ) {
    Bar b;
    Foo f;
    function(b,f);
}

int main ( ) {    
    otherFunction ( &Bar::function );
                    ^^^
                   error
}

I understand that the compiler cannot deduce which overload to use, so the next best thing to do is a static_cast, but the following code still has the same error

std::function<void ( Bar& , const Foo& )> f = static_cast< std::function<void ( Bar& , const Foo& )> > ( &Bar::function );
like image 815
Midnight Exigent Avatar asked Dec 13 '22 11:12

Midnight Exigent


1 Answers

You need to cast to member-function pointer, not to std::function:

otherFunction ( static_cast<void(Bar::*)(const Foo&)>(&Bar::function) );

Live

[EDIT]

Explanation:

otherFunction ( &Bar::function );

otherFunction takes std::function as a parameter. std::function has an implicit constructor (an implicit conversion) from a function pointer (a member function or a free function, and other "callable" types, doesn't matter here). It looks like this:

template< class F > 
function( F f );
  • it's a template parameter
  • while F is "callable", it doesn't specify the signature of F

This means that compiler doesn't know which Bar::function you meant, because this constructor doesn't put any restrictions on input parameter. That's what compiler is complaining about.

You tried

static_cast< std::function<void ( Bar& , const Foo& )> > ( &Bar::function );

While it looks like compiler has all details it needs here (the signature), actually the same constructor is called, so nothing effectively changed. (Actually, the signature is incorrect, but even correct one wouldn't work)

By casting to a function pointer we provide its signature

static_cast<void(Bar::*)(const Foo&)>(&Bar::function)

So ambiguity is resolved as there's only one such function so compiler is happy.

like image 138
Andriy Tylychko Avatar answered Jan 12 '23 04:01

Andriy Tylychko