Adrien Clerc
Adrien Clerc

Reputation: 2797

std::function< void ( const A & )> can't cast to std::function< void ( const B & ) > when B inherits from A

I am currently trying to store some listeners in a std::vector, and call them when needed. I have the following definitions in the base class:

class A
{
public:
    virtual ~A();
    typedef std::function< void( const A & ) > Listener;
    std::vector< Listener > listeners;
    void addListener( const Listener & listener)
    {
        this->listeners.push_back( listener );
    }
}

I have a simple B class:

class B : public A
{
    virtual ~B();
}

All I want to do is be able to write a call like this:

B b;
b.addListener( [] ( const & B ) { /* Do something */ } );

But this doesn't compile, with the following error:

error: no viable conversion from '<lambda at main.cpp:158:27>' to 'const Listener' (aka 'const function<void (const A &)>')

I am currently avoiding this issue with dynamic_cast, but it seems a bad thing, or a bad design to me…

Upvotes: 2

Views: 511

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

Consider normal functions first. Just because A and B are related types and you can cast between them, that doesn't mean that the types of the functions void f(const A&) and void g(const B&) are related, and pointers to those functions are not convertible to each other.

Similarly, SomeTemplate<A> and SomeTemplate<B> are not related types and cannot be converted to each other.

I hope now it makes sense that std::function<void(const A&)> and std::function(void(const A&)> are unrelated types and not convertible back and forth between each other.

Upvotes: 3

Related Questions