Explicit default constructor for structs

monarch_dodra monarchdodra at gmail.com
Thu Apr 10 04:13:43 PDT 2014


On Wednesday, 9 April 2014 at 18:41:57 UTC, Walter Bright wrote:
> On 4/9/2014 7:59 AM, Benjamin Thaut wrote:
>> What do you think? C&C welcome.
>
> Or you could use a factory function:
>
>   struct Foo {
>     static Foo factory() { ... }
>     ...
>   }
>
>   auto foo = Foo.factory();

Yeah. For sure.

Or a named function: auto foo = foo();
Or a make template:  auto foo = make!Foo();
Or a dummy argument: auto foo = Foo(Foo.dummy);
Or ditto with a global dummy:  auto foo = Foo(dummyArg);
Or use a static opCall:        auto foo = Foo();
Or use an initialize function: Foo foo; foo.initialize();

I mean: Why complain when there are at least 10 *different* 
solutions at our disposal? Who doesn't love re-inventing the same 
functionality over and over and over again? But more importantly, 
who doesn't just *love* reading the documentation that explains 
*which* approach the damn type chose for run-time initialization. 
Yummy!

Also, any kind of "Factory" solution has a postblit overhead if 
you try to emplace it. Or would require a temporary with some 
complex "uninitializedMove". No postblit, but still overhead.

--------

Being serious again, if the language isn't going to do something 
to address the issue, we *should* have a uniform library solution.

I think the "make" template could be a good approach. It could be 
a universal construction scheme, with "opt-in" no-arg 
construction:

static struct NoArg {}
enum noArgToken;

template make(T)
{
     //And some switches to handle non-struct types too.

     T make(Args...)(auto ref Args args)
     {
         static if (Args.length)
             return T(args);
         else
         {
             static if (is(typeof(T(noArgToken))));
                 return T(noArgToken);
             else
                 return T();
         }
     }
}

struct S1
{
     int* p;
     @disable this();
     this(NoArg) //Opt-in no-arg constructor
     {p = new int;}
}
struct S2
{
     int i;
}

void main()
{
     S1 s11; //FAils to compile (disabled this());
     auto s12 = S1.init; //Explicit request for static default 
initialization;
     auto s13 = make!S1(); //run-time construction request.

     auto s2 = make!S2(); //run-time construction request. Does 
nothing particular.
}

This has the advantage (IMO) of being explicit and universal. 
Also, it's an actual construction scheme, so 
`emplace(noArgToken)` would call an actual constructor.

Furthermore, it could also allow a universal construction scheme 
for items, regardless of struct/class/integral etc...


More information about the Digitalmars-d mailing list