Suppose we have the following hierarchy:
class Add3Interface {
virtual int add3 (const int&) const = 0;
};
class Add3: public Add3Interface {
virtual int add3 (const int& arg) const override {
return arg + 3;
}
};
I want to bind the add3 method so I can use it in things like std::views::transform.
The following code is fine:
const Add3 myAdder{};
const auto myFun = std::bind(&Add3::add3, myAdder, std::placeholder::_1);
However, in my use case, I don't have access to the concrete type, so I have to write something like this:
auto foo(Add3Interface& myAdder) {
const auto myFun = std::bind(&Add3Interface::add3, myAdder,
std::placeholders::_1);
// ...
}
However, this makes the compiler upset:
/usr/include/c++/11/tuple:238:13: error: cannot declare field ‘std::_Head_base<0, Add3Interface, false>::_M_head_impl’ to be of abstract type ‘Add3Interface’
How can I bind my object's method?
I hoped something like typeid might help:
const auto myFun = std::bind(&(typeid(myAdder)::add3), myAdder, std::placeholders::_1);
But that only led to various syntax errors, which differed depending on how I positioned the various parentheses.
Naturally we could just use a lambda:
const auto myFun = [&myAdder] (const auto& arg) { return myAdder.add3(arg); };
But I'd prefer to use bind if possible, as I feel it represents what I am trying to do better from a semantic point of view.
std::bindattempts to store all of its arguments by-value. In this case, it is trying to copymyAdderinto a data member of typeAdd3Interface. Of course, asAdd3Interfaceis abstract, this fails. The issue is not with the member function pointer having the wrong type.If you want
std::bindto refer to a stored argument by reference, pass astd::reference_wrapper<T>instead of aT. You can use the convenience functionsstd::reforstd::crefto constructstd::reference_wrappers.(To be precise,
std::binddoesn't itself handlestd::reference_wrapperspecially at all. It will just store a copy of thestd::reference_wrapperas a data member just like it stores a copy of any other argument. Thestd::reference_wrapperis correctly unwrapped at the time of the function call because the standardINVOKEoperation that many standard utilities use to invoke callables unwraps it.)