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