| There is a phrase that might be confusing for those who do not know Ada: "As a historical note, earlier versions of Ada forbade reading from out variables, which allowed more efficient calling conventions, but modern Ada allows it because otherwise people went insane." What is meant is that the "out" parameters behave like local variables without initializers, which upon entry into a function are likely to have invalid values. Therefore you cannot read an "out" parameter before assigning a value to it. After the first assignment, it can be read or written at any time before the function returns. Depending on the type, an "out" parameter is implemented as either a CPU register whose value is unknown upon function entry or as a reference to a memory area allocated in the caller, but uninitialized. The specification of the function parameters as "in", "out" or "in out" and the irrelevance and transparency of how the compiler chooses to pass the parameters is one of the best features of Ada. This has not been invented by the creators of Ada, but it has been invented by some anonymous Department of Defense employees or contractors. This feature was included in the DoD "Requirements for High Order Computer Programming Languages", "IRONMAN" from the July 1977 revision. It was probably already present in the first version of "IRONMAN" from January 1977. It is a huge mistake in the design of almost all programming languages that have appeared after Ada that they do not include this feature. The lack of distinction between "out" and "in out" parameters has serious consequences especially for the object-oriented languages. The lack of this feature has caused a very large part of the complexity of C++ and also most of the performance problems of the C++ versions from before 2011. When "out" and "in out" parameters are distinguished, there is no need for the existence of constructors as a separate concept. Any ordinary function with an "out" parameter can be used wherever C++ requires a dedicated constructor. Instead of constructors, it is enough to have an identifier convention for functions that should be called by the compiler when you want implicit initialization or implicit conversions. Moreover, there is no need to care about "copy" semantics and "move" semantics or about temporaries which are or which are not generated by the compiler. It is easy for the compiler to always choose the best implementation without programmer intervention, when it knows the correct parameter modes for the functions. |
Why do we need "out" vs "in out" parameters for this? Why can't a function that returns the object work just as well? And "an identifier convention for functions that should be called by the compiler when you want implicit initialization or implicit conversions" seems essentially the same as constructors to me.
>Moreover, there is no need to care about "copy" semantics and "move" semantics or about temporaries which are or which are not generated by the compiler. It is easy for the compiler to always choose the best implementation without programmer intervention, when it knows the correct parameter modes for the functions.
How would I implement something like std::vector with deep copy and move support of its contained objects without writing copy and move constructors (or operators)? There needs to be code saying "allocate a new block of memory and copy all the elements to that new block", and code saying "just copy the pointer, and set the other pointer to null". Are you saying the implementer would still write that code, just not in constructors/operators? How is that better?