Le 11/10/2012 16:35, Andrei Alexandrescu a écrit :
On 10/11/12 9:52 AM, deadalnix wrote:
Le 11/10/2012 14:19, Andrei Alexandrescu a écrit :
Temporary object are used to store temporary state coming from some
computation. In this case, the computation create the complexity, the
object isn't created via default constructor.
Or have you a use case in mind I don't think of ?
Here I meant a named temporary, such as e.g. a pivot in quicksort.
Well a pivot is not built out of nothing. So I don't see why any
constructor have to be involved here.
However, postblit will be involved and can be of arbitrary complexity
already.
3. Two-phase object destruction (releasing state and then deallocating
memory), which is useful, is made more difficult by default
constructors. Essentially the .init "pre-default-constructor" state
intervenes in all such cases and makes it more difficult for language
users to define and understand object states.
This one is made worse by the current state. You have to assume
everywhere that your struct can be .init
Even when it doesn't make any sense. RefCounted is a pathologic case of
that.
One point I was making is that even with a default constructor, the
definition and existence of .init pops all over the place, like a bubble
in the carpet. I think it is a good engineering decision to simply make
it the default state.
A giveaway state (as compile time state, not as runtime state) solve
that problem nicely.
4. Same as above applies to an object post a move operation. What state
is the object left after move? C++'s approach to this, forced by the
existence of default constructors and other historical artifacts, has a
conservative approach that I consider inferior to D's: the state of
moved-from object is decided by the library, there's often unnecessary
copying, and is essentially unspecified except that "it's valid" so the
moved-from object can continue to be used. This is in effect a back-door
introduction of a "no-resources-allocated" state for objects, which is
what default constructors so hard tried to avoid in the first place.
If we give struct a giveaway state (where the struct cannot be used
unless it is reinitilized to a correct value) this problem disappear.
It doesn't disappear - it manifests itself in a different way
(complexity in the language definition).
The complexity will have to be introduced anyway to handle @disable
this() properly, so I don't really see that as an added complexity. It
is more like getting the most of the complexity that is already planned
to be added.
Except in the case 5. (and heap allocated struct in general), that in
fact seems to me the major issue.
I agree heaps with required allocated state are unpleasant to deal with
in the current design.
My overall point, which is worth repeating, is not that these problems
are insurmountable. Instead, we're looking at different choices with
distinct tradeoffs. There's no solution with all pluses.
Well, why not let the programer make the choice ? Nothing have to change
in regard to struct with no default constructor. And no complexity is
added for existing stuffs.