What is the case against a struct post-blit default constructor?
Malte Skarupke
malteskarupke at web.de
Wed Oct 10 18:15:27 PDT 2012
Hi, thanks for the detailed answers.
So I am very much for keeping init. I just want that if the user
specifies a default constructor, it is being called after the
value has been initialized to init.
> On Wednesday, October 10, 2012 21:11:29 foobar wrote:
>> Arrays - without changing existing syntax we can use these
>> semantics:
>>
>> auto a = new int[](5); // compiler calls T() for each instance
>> int[12] b; // ditto
>
> And what on earth does that buy you over init? That's what init
> _does_. And
> since the value needs to be known at compile time (otherwise
> arrays won't work
> for directly initializing _anything_ that needs to be
> initialized at compile
> time), a constructor really doesn't buy you anything here at
> all. init
> provides a nice, consistent way of initializing or assigning a
> value to a
> variable as well as providing a consistent default state for a
> type when you
> need to be able to set a variable of that type to a consistent,
> safe state
> (e.g. with std.algorithm.move). And as built-in types don't
> _have_
> constructors, there's no other way for generic code to
> generically initialize
> anything.
"What does this buy you over init?" This would help with structs
that can't be initialized to a valid value at compile time.
So what I expect to happen in a line like
S[12] s;
Is that they all get blitted to init, followed by a loop that
calls the default constructor on each of these. If there is no
default constructor, they stay at init and the loop doesn't
happen.
This would work with user defined types and with built-in types.
If a constructor throws an exception, then the array is correctly
initialized up to the element before the throwing one. The
remaining elements are at init.
For member variables I expect this to happen:
If one of your member variables has a default constructor but you
do not, then the compiler will generate an empty default
constructor for you. This gives your object the same behavior in
arrays as described above, which means that the member variable
will always be correctly initialized using both init and the
deafult constructor.
If one of your member variables has a default constructor, and so
do you, then the member variable's default constructor is called
before your default constructor.
If an exception is thrown, the containing object remains at the
state it is in (most likely init)
If you do not want the default constructor of your member
variable to be called, you can declare it as S s = S.init;
For emplace I expect that the default constructor gets called.
For std.algorithm.move you'd have to define which state the
source object is in after moving. Since it's a destructive move,
I'd expect the object to be at init, as if a destructor had been
called. You could implement that with a tiny change to the
current implementation. (memcpy from init instead of a statically
allocated instance)
This should cover all the cases that you mentioned. It is highly
performant (in fact this is very close to the behavior in C++,
but faster because it uses init) and it won't affect structs that
can be initialized at compile time. It will only be used for
cases where you need to do things at runtime, and the users have
the full ability to shoot themselves in the foot if they want to.
More information about the Digitalmars-d
mailing list