I’m getting errors when trying to pass a function using deducing-this to std::bind. See the example below.
#include <iostream>
#include <functional>
struct A {
void foo_deducing_this(this auto& self, int x) {
self.bar(x);
}
};
template <typename Deriv>
struct B {
void foo_crtp(int x) {
static_cast<Deriv *>(this)->bar(x);
}
};
struct C : A, B<C> {
void bar(int x) {
std::cout << "number is " << x << "\n";
}
};
void test(const std::function<void(int)>& f, int x) {
f(x);
}
int main() {
C c;
c.foo_deducing_this(1);
c.foo_crtp(2);
c.bar(3);
// this doesn't compile
// test(std::bind_front(&C::foo_deducing_this, c), 5);
test(std::bind_front(&C::foo_crtp, c), 6);
test(std::bind_front(&C::bar, c), 7);
}
I’d like to use deducing this to avoid some templates required by CRTP but still taking advantage of the same pattern. Using boost beast the pattern seems to be to pass callbacks around with
stream.async_read(buffer,
beast::bind_front_handler(&Connection::on_read,
this->shared_from_this()));
So my Connection callbacks need to support being "binded" to and that seems to be an issue when using deducing this but I can’t figure out why.
EDIT: This was tested on clang 18.1.0. Godbolt link.
>Solution :
"Deducing this" changes the member to a templated-function, even if you do not explicitely specify template<>, but instead "auto" as a parameter. This means that it’s no longer clear which variant of foo_deducing_this would be requested when trying to get a function-ptr.
You can see that it’s not related at all to std::bind (and get a more sensible error), if you simply put this line in your code:
&C::foo_deducing_this;
This results in clang emitting the following error:
<source>:34:5: error: reference to overloaded function could not be resolved; did you mean to call it?
34 | &C::foo_deducing_this;
| ^~~~~~~~~~~~~~~~~~~~~
You can specify the correct overload by casting the type of member-function ptr in the call to std::bind_front (which must include the expected const-ness):
using MemberFuncPtr = void (*)(A&, int);
std::bind_front((MemberFuncPtr)&A::foo_deducing_this);
or even simpler, specify the template parameter:
std::bind_front(&A::foo_deducing_this<A&>);
Interestingly (which is why I left the casting-example in), it seems that this function is now no longer even a true member-function. Didn’t even know that, but I have not much experience with deducing this.