Skip to main content

Timeline for The "blub paradox" and c++

Current License: CC BY-SA 3.0

13 events
when toggle format what by license comment
Apr 29, 2019 at 15:06 comment added Caleth Let us continue this discussion in chat.
Apr 29, 2019 at 15:04 comment added cmaster - reinstate monica @Caleth While it's possible in Objective-C to pass object(s) and selector(s) at different times, the usual usecase was to pass them together. A button's action, for instance, could be set with a single call that passed both object and selector. The only exception to this that I am aware of was the generic array type that included a member function that took only a selector and invoked it on all the objects stored in the array - an operation that was used rather sparingly, and is rather questionable IMHO. That's why I think that the bundled object and member approach is a better C++ equivalent.
Apr 29, 2019 at 14:40 comment added Caleth @cmaster I was assuming the object(s) and the member(s) to call were passed to the library at different times
Apr 29, 2019 at 14:39 comment added cmaster - reinstate monica @Caleth Ah, ok, so basically the type-deleted closure idea. Nevertheless, why not just include the object pointer in the closure? Like template<class ClassT> std::function<Ret()> make_erased(ClassT* o, Ret(ClassT::*member)()) { return [o, member](){ return (o->*member)(); }; } This should work perfectly in C++, and is probably the most fitting solution in most cases. Frankly, I didn't grasp the intended use of std::function<> when I wrote this answer 3 years ago, it's what makes this kind of parameter passing possible. Nevertheless, Objective-C doesn't require such complex incantations...
Apr 29, 2019 at 14:08 comment added Caleth @cmaster among others void *, and std::function<Ret(void*)>, aided by a wrapper like template<class ClassT> std::function<Ret(void*)> make_erased(Ret(ClassT::*member)()) { return [member](void * ptr){ return (static_cast<ClassT>(ptr).*member)(); }; }. You still need to co-ordinate that object of the correct type are used, so it's often easier to expose it as a template
Apr 29, 2019 at 13:59 comment added cmaster - reinstate monica @Caleth Now you got me curious: You mean, it's possible to pass both an object pointer and a pointer to one of its members to a dynamically linked library function, and have that library function call the object's member function correctly without knowing the object's type? I would have thought that you need to encapsulate both object and member function pointer into a closure that is passed via std::function<> to achieve type deletion. More precisely: What argument types would the library function need to accept to allow passing an arbitrary member function of an arbitrary object?
Apr 29, 2019 at 9:02 comment added Caleth @cmaster C++ let's you construct a std::function<Ret(ClassT)> from &ClassT::Member, i.e. the name of a member function, similarly Java's ClassT::Member, similarly C#'s o -> o.Member()
May 20, 2016 at 6:11 comment added cmaster - reinstate monica @Jules Your arguments are precisely what the Blub-Paradox is about: As a proficient C++ programmer, you don't see these as limitations. However, they are limitations, and other languages like C99 are more powerful in these specific points. To your last point: There are workarounds possible in many languages, but I don't know one that really allows you to pass the name of any method to some other class and have it call it on some object that you provide as well.
May 19, 2016 at 17:02 comment added Jules "I have not seen a similarly flexible way to define a callback in any other language yet (though I'd be very interested to hear about them!). " -- in Java, you can write object::method and it will be converted into an instance of whatever interface the receiving code expects. C# has delegates. Every object-functional language has this feature because it's basically the point of cross-section of the two paradigms.
May 19, 2016 at 16:58 comment added Jules "In C++ you cannot write down the type of a lambda. You can't even typedef it. Thus, there is no way to pass around a lambda, or store a reference to it in an object" -- that's what std::function is for.
May 19, 2016 at 16:57 comment added Jules "In C++ you cannot write down the type of a VLA" [...] -- in C++, C99-style VLAs are unnecessary, because we have std::vector. While it's a little less efficient due to not using stack allocation, it is functionally isomorphic to a VLA, so doesn't really count as a "blub" type issue: C++ programmers can look at how it works and just say, "ah yes, C does that more efficiently than C++".
May 18, 2016 at 21:10 comment added Mason Wheeler I have not seen a similarly flexible way to define a callback in any other language yet (though I'd be very interested to hear about them!) What you just describes sounds exactly like the way event-driven UI code works in Delphi. (And in .NET WinForms, which was heavily influenced by Delphi.)
May 18, 2016 at 21:03 history answered cmaster - reinstate monica CC BY-SA 3.0