6 ms·
>C++ provides two calling syntaxes, x.f(y) and f(x,y) I have to shamefully admit, I have no idea what this is referring to. In the second one, is this talking
by hellofunk 11y ago
>C++ provides two calling syntaxes, x.f(y) and f(x,y)
I have to shamefully admit, I have no idea what this is referring to. In the second one, is this talking about the implicit "this" pointer that is passed to member functions?
I've never seen or written code like the second form -- if in fact f() is defined as taking only a single argument, I've never seen it called with 2 arguments.
My guess is that this is a discussion about the implementation of member functions, can anyone confirm?
- kamac 11y agoI think they're referring to OO style (a member function) and imperative style (loose functions). But unifying those makes no sense to me.
- pjmlp 11y agoQuite a few languages do OOP f(self, args), not every OOP language does self.f(args). Ada, Common Lisp and Dylan come to mind.
- efaref 11y agoUnder the covers, `x.f(y)` is actually something like `_ZN1X1fEi(&x, y)`, where the mangled name indicates the class of X and the type of y. The implicit 'this' pointer is actually explicit in the implementation. Similarly, a call to `f(&x, y)` would actually be a call to `_Z1fP1Xi(&x, y)`, with similar reasoning. The author is proposing that writing f(x, y) Which would normally only bind to the second mangled function, would bind to the first mangled function if the second is not available. The additional proposal, that: x.f(y) would work in the other direction was rejected. That's a bit of a shame, as this kind of duality is powerful in languages that support it (e.g. scala).
- daemin 11y agoThis is also why functions can work on a null object and not crash, as long as they do not access instance data. Though at that stage they should be static or external.
- efaref 11y agoYes, except for calls to virtual functions, which actually become (&x)->vtbl[N](&x, y)
- twoodfin 11y agoAFAIK, this is still undefined behavior, so "can work" means "you got lucky this time, your next compiler upgrade may turn this into a crash, security vulnerability, or utterly confounding Heisenbug".
- blt 11y agoUgh, I remember seeing null `this` values used on purpose in some old Windows MFC program, or maybe it was COM... I imagine the author was an old-school C programmer who understood well how the C++ object veneer maps down to equivalent C code / assembly. From that perspective, dealing with null `this` pointers is just another way to get the compiler to spit out the assembly instructions you want, and maybe enables some elegant patterns in client code... but it's exactly the kind of thing that makes newcomers hate C++.
- akavel 11y agoBased on the rest of the original paragraph, I understand he refers to the fact that you have to choose either one when desigining a library, and then you're stuck with it (and its various consequences) in your API for better or worse -- and your library users are stuck with it too. In other words: if you design a polygon clipping library, do you design your API so that users would write `polygon1.clip(polygon2)`, or `clipper::clip(polygon1, polygon2)`? edit: also, from reading further down, I understand the discussed issue is that after you define the API as `polygon1.clip(polygon2)`, you can't easily use the 'clip' method in places where a f(a,b) would be required, although it's effectively equivalent. And it's impossible the other way round too.
- roel_v 11y agostd::function works like the second syntax. struct Foo { void Bar(int) {} }; std::function <void(Foo&, int)> f = &Foo::Bar; int i; Foo foo; f(foo, i); Which is confusing - you'd expect it to work like maybe 'foo.f(i)' or maybe 'foo.*f(i)' or something like that. Well the whole discussion (from what I understand) is what that 'something' should be (well I don't mean to imply that this is about how std::function should work; rather that this is one explicit manifestation of an issue that shows in several places).