[BUG] Documentation of this/that copy/move ctor/assignment is very confusing and needs significant improvements
This is more of a suggestion than a bug but I see your suggestion template is aimed at language features so I write this issue as a bug because I think most readers won't be able to make use of mentioned docs effectively or at all.
The issue IMO the docs about RAII (https://hsutter.github.io/cppfront/cpp2/types/) are a mess. I'm fairly versed in this stuff yet I find it very unintuitive to write any special member function in Cpp2 and understand the concepts in new syntax. All tried on cppfront built from 5aa32aef7c74679994d6da39e6d0cf9b9714e1ee.
-
The docs start with describing
this, then go aboutvirtualand inheritance stuff and then back to RAII but in the form ofoperator=andthat. IMO virtual/inheritance stuff should be at the bottom. The split ofthisandthatsections with intermediate less-related section makes it hard to read and creates unnecessary cognitive burden. -
Some of provided examples do not work. The first section says "
out this: Writingmyfunc: (out this /*...*/)defines a Cpp1 constructor... and more. (See below.)" yet when I try to compile anything likemyfunc: (out this)ormyfunc: (out this, y: std::string)I get a fairly unclear error "error: a function with an 'out this' parameter must be a constructor" - I just tried to write a constructor as the docs say and it is not one? -
Some of provided examples do not work. The part about destructors in the first section is just incorrect. It says "
move this: Writingmyfunc: (move this /*...*/)defines a Cpp1&&-qualified member function, or if there are no additional parameters it defines the destructor." but when I trydtor: (move this)I'm gettingauto dtor() && -> void, not a real dtor. -
There are 2 ways to write a destructor (according to documentation):
myfunc: (move this)according tothissection (doesn't work as in 3)) andoperator=: (move this)according tothatsection (this one is correct). -
I can easily generate some nonsense:
myfunc: (this, move that)producesauto myfunc(X&& that) const& -> voidwith notableconst&-qualifier and&¶meter. This is valid C++ but pretty much useless code. -
The infographic about
operator=generation is awesome but IMO its value is diminished by the lack of consistent examples: many special member functions are explained (I guess incorrectly?) onmyfunc, notoperator=.
My suggestions:
- merge
thisandthatsections into one - put virtual/inheritance stuff after all RAII stuff
- make a cheatsheet of all common functions (static, const&-member, &-member, &&-member, ctor, converting ctor, copy/move ctor/assignment, dtor) (how to write, respective current C++ and whether they generate more functions)
- provide canonical examples of rule-of-zero class with fancy converting ctor/assignment, rule-of-cpp2 copyable class and rule-of-cpp2 moveable class
Here is a cheatsheet I came up with after few hours of testing cppfront with various examples of random class X and some deduction in my head:
f: (/* no this/that */) // static function
f: ( this /*...*/) // const&-qualified member function
f: (inout this /*...*/) // &-qualified member function
f: ( move this /*...*/) // &&-qualified member function
operator=: (out this) // default ctor
operator=: (out this, Y) // converting ctor + converting assignment
operator=: (out this, Y, /*...*/) // user-defined ctor
operator=: (move this) // destructor
operator=: ( out this, that) // copy ctor + move ctor + copy assignment + move assignment
operator=: ( out this, move that) // move ctor + move assignment
operator=: (inout this, that) // copy assignment + move assignment
operator=: (inout this, move that) // move assignment
Note that for member functions /*...*/ is without , which indicates possibly no more extra parameters but there is , for user-defined ctor.
You mentioned a few things that cppfront could not parse or where not providing the expected results. Could provide an example file on what did not work?
All of such examples are already in my first post. They are either rejected as invalid functions (2, 4) or generate nonsense code (3, 5).
Yes that is true. But a direct example file, that one could use, would make it for other people simpler to reproduce the errors/nonsense code.
Sure.
// uncomment one function at a time
X: type = {
x: std::string = "abc";
// 2. "error: a function with an 'out this' parameter must be a constructor"
//f2a: (out this) = {}
//f2b: (out this, y: std::string) = { x = y; }
// 3. produces nonsense "auto f3dtor() && -> void" instead of a real dtor
//f3dtor: (move this) = {}
// 4. second way to write a dtor - this one works
//operator=: (move this) = {}
// 5. produces nonsense "auto f5func(X&& that) const& -> void { x = cpp2::move(that).x; }"
//f5func: (this, move that) = { x = that.x; }
}
Ok, thanks. Just a quick reply:
Case 2 should be:
operator=: (out this) = {}
operator=: (out this, y: std::string) = { x = y; }
And now I understood your comment with respect to 2. So the example should be modified to
out this: Writing operator=: (out this /*...*/) defines a Cpp1 constructor... and more. (See below.) from
out this: Writing myfunc: (out this /*...*/) defines a Cpp1 constructor... and more. (See below.)
And the error should add a hint, e.g. use operator= as the function name for a constructor.
Will take a closer look during the week.
Yes exactly. I think the biggest issues the documentation has are that:
- sections are split (virtual in between) and have overlapping/conflicting examples (e.g. 2 different ways to write a dtor)
- most (if not all) incorrect examples are written as
myfuncbut should beoperator=
Sorry about the error. I wrote that. I agree it would be better to specify that constructors should always be operator=.