Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

deducing this and std::bind

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading