The goal is to get a functor to the Base::Print
.
#include <functional>
#include <iostream>
using namespace std;
class Base {
public:
virtual void Print() {
cout << "Base" << endl;
}
virtual function<void()> get_fx1() {
return bind(&Base::Print, this);
}
virtual function<void()> get_fx2() {
return bind(&Base::Print, *this);
}
};
class Derived : public Base {
public:
virtual void Print() override {
std::cout << "Derived" << std::endl;
}
};
int main()
{
Derived d;
Base *ptr = &d;
ptr->Base::Print(); // prints Base (expecetd) #out1
bind(&Base::Print, ptr)(); // prints Derived (expected Base) #out2
ptr->get_fx1()(); // prints Derived (expected Base) #out3
ptr->get_fx2()(); // prints Base (expected Derived because of out2 and out3) #out4
cout << " -- " << endl;
Derived d2;
Base& ref = d2;
ref.Base::Print(); // prints Base (expected) #out5
bind(&Base::Print, ref)(); // prints Base (expected Derived because of out2 and out3. But this matches the behaviour with out4) #out6
cout << " -- " << endl;
(&ref)->Base::Print(); // prints Base (expected) #out7
bind(&Base::Print, &ref)(); // prints Derived (I give up) #out8
return 0;
}
I assumed that passing a pointer or a reference to std::bind
is exactly the same. Clearly, I was wrong. It seems like when a reference is passed to std::bind
you can prevent the vtable lookup. But when a pointer is passed to std::bind
there is no way to prevent the vtable lookup. Empirically this is what it seems like.
So, the question is: does std::bind
selectively skip the vtable lookup when a reference is passed?
I didn't find any reference only stating this.
Edit: Link to Compiler Explorer
std::bind()
cannot bind "normal" references. You are slicing your derived class to your base class, and then calling the virtual function on the sliced object. For which the virtual call correctly calls the base class function.
std::ref(...)
can be used to bind functions that want references: