no-arg constructor for structs (again)

monarch_dodra monarchdodra at gmail.com
Wed Sep 19 11:38:11 PDT 2012


On Wednesday, 19 September 2012 at 18:08:15 UTC, Dmitry Olshansky 
wrote:
> On 19-Sep-12 15:52, monarch_dodra wrote:
>> I realize *why* the "default" constructor had to go, but 
>> "no-arg" didn't
>> have to go with it. I think it was an accident to let it go, 
>> and we
>> should be trying to fix this.
>
> I do not feel that there is a lot of reference-like types that 
> take 0 arguments at construction. Any meaningful examples?

There are not a lot currently. RefCounted is. PRNG should 
arguably be migrated to them. Containers are kind of a hybrid 
(but this seems to be more of a implementation detail than by 
concept).

> About checking for "was initialized" it is indeed painful, yet 
> I believe even C++ is in the same boat (empty shared_ptr?). 
> Also I do suspect that in the majority of cases these are just 
> asserts since they aim to catch logic errors in code.

No, because C++ has default constructor. Regarding D's logic 
error, the problem is that the lack of "no-arg" underminds the 
definition of "logic error": More below!

> Having a way to ensure initialization statically would be nice. 
> Currently only @disabling this() would achieve that but I 
> suspect it's somewhat bogus ATM.
>
> In fact having @disable this() undermines the argument for 
> "always have T.init" strategy as generic code now have to deal 
> with both cases.
>
>> Could I get some feedback so I could make a formal and thorough
>> enhancement request?
>
> I'd rather see static opCall go and be replaced with no-arg 
> constructor. But this alone doesn't bring much benefit (if any).

Here is a concrete example:

import std.random, std.typeconv;

void main()
{
     alias RefCounted!(int, RefCountedAutoInitialize.no) RCI; 
//RefCountedInt
     RCI a;                      //NOT initialized
     RCI b = RefCounted!int(15); //Initialized
     RCI c = RefCounted!int();   //Initialized to int.init ... ?

     int i;

     i = a; //Logic error
     i = b; //Ok
     i = c; //Logic error?
}

The issue here is with "c". Arguably, it was not initialized. 
Arguably, the intent was, as opposed to "a", to initialize it to 
it's default value. At that point, is trying to read c a logic 
error? And if it is, can you really blame the user?

Same example with PRNG:

void main()
{
     alias ... PRNG;
     PRNG a;                      //NOT Seeded
     PRNG b = RefCounted!int(15); //Seeded
     PRNG c = RefCounted!int();   //Seeded with default seed...?

     a.front(); //Logic error
     b.front(); //Ok
     c.front(); //Logic error?
}

Ditto. Will the user really understand that b was seeded, yet c 
wasn't. This is even more ambiguous that PRNG *does* have a 
"seed()" method with a default seed

I know for a FACT that _I_ would have expected c to be default 
seeded. This makes the prng *VERY* ambiguous about whether or not 
it was seeded :/

Basically:
To seed with 15: PRNG b = RefCounted!int(15); //Seeded, yay
To default seed: PRNG c = RefCounted!int(); c.seed(); //  What...?

The opCall hack would fix the issue in the above example, but as 
stated in the previous thread, it is just that, a hack: You can't 
use it to construct inplace with emplace!(T, Args...), nor can 
you take it's address, nor can you use it to new it (should you 
ever want to do that.)


More information about the Digitalmars-d mailing list