Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Most of what the author complains about w.r.t callbacks is fixed with std::function and lambdas (member function pointer syntax is necessarily weird, because methods aren't just normal functions). I definitely don't miss the days of std::bind. Nowadays you just do something like

    using Callback = std::function<int(int)>; // or whatever
    Callback cbk = [&](int i) { return instance.method(i); };
I've also seen some real evil hacks that rely on casting 0 as a pointer to a class and relying on the ABI's spec for vtable layout to calculate the pointer of the function as an offset from the `this` pointer. Because that's easier to remember than the syntax for pointer-to-member functions.


It is notable that this code forces a conversion to std::function which IIRC can actually require more space than the lambda it's attempting to store. For lambdas just use auto they don't have a type don't worry about their type.


What's so awful about pointer to member? I've used it a couple of times, and didn't think it was particularly weird. I mean, yes, I had to look up the syntax, but it was rather straightforward.


there is nothing wrong with them, but pointers to member do not close over this, so you still need some form of binding to use them as callbacks.


Well, when you invoke a pointer to member, you need an actual object (a this) to invoke it on. So when the member runs, it has a this.

But it sounds like what you want is a "handle" or some such term, by which you can invoke a member function on an object, and all you need to do so is the handle. That's a different problem than pointers to members are trying to solve, but you can do that quite easily with a function object. That's essentially a roll-your-own closure, and since you can define whatever data members you want, you can close over anything.

One thing you have to watch out for, though, is lifetimes. C++ is not garbage-collected, and so it will not preserve an object just because another object has a pointer or reference to it. If you create a function object that captures a pointer to member, and a "this" to invoke it on, and the "this" gets destroyed, and then you use the function object, you're going to get chaos.


Using lamdba's requires grappling with entirely new syntax compared to anything else in C++ (or C).

Using various bind equivalents just requires you to know what you're doing:

boost::function<int(int)> cbk = boost::bind (&SomeObject::some_method, instance_of_some_object);

...

cbk (22); // invoke callback

In addition, the author's complaints about nobody using ptr-to-method is absurd. Even in 2010, anyone using libsigc++ or its (few) equivalents was using them, which meant that any GUI app written using GTKmm was full of them. What's not to love?


There's also

  Callback cbk = std::bind_front(instance, Instance::method);
in C++20. I'm going to ignore std::bind as it has weird conventions. :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: