Thread overview
hacky way to get explicit default constructor on struct :P
Oct 28, 2017
LunaticWare
Oct 28, 2017
Jonathan M Davis
Oct 31, 2017
Dmitry Olshansky
October 28, 2017
Event if there is no default constructor on struct we can still make one that work as well as if it were implemented, here is my example n__n

------

import std.format;
import std.stdio;

struct Player
{
    string name = "Baz";
    float[2] position = [0, 0];

    // Adding an explicit constructor to struct =)
    // But we can't enforce it since this relies on it =(
    static ref auto opCall(string name = "Bar", float x = 1, float y = 1)
    {
        // Even if we give no argument opCall will still be called ;)
        writefln("Entering the explicit constructor as '%s'", name);

        // Taking advantage of the implicit constructor
        Player self;

        // Initializing all the members
        self.name = name;
        self.position[0] = x;
        self.position[1] = y;

        // Returning the reference of the object
        return self;
    }

    string toString()
    {
        return format("Hello i am '%s' and at the coordinate x%s / y%s",
            this.name, this.position[0], this.position[1]);
    }
}

void main()
{
    auto foo = Player("Foo", 2.7, 10.6);
    auto bar = Player();
    Player baz;

    writefln("%s\n%s\n%s", foo, bar, baz);
}

// == RDMD OUTPUT ==
// Entering the explicit constructor as 'Foo'
// Entering the explicit constructor as 'Bar'
// Hello i am 'Foo' and at the coordinate x2.7 / y10.6
// Hello i am 'Bar' and at the coordinate x1 / y1
// Hello i am 'Baz' and at the coordinate x0 / y0

October 28, 2017
On Saturday, October 28, 2017 16:59:03 LunaticWare via Digitalmars-d wrote:
> Event if there is no default constructor on struct we can still make one that work as well as if it were implemented, here is my example n__n

This idiom gets suggested from time to time, and I'm sure that it gets used some, but AFAIK, it's never really caught on much. I think that it's something that tends to look nice at first for someone looking for a default constructor but that ultimately, you're better off with other solutions.

Using static opCall allows you to get MyType() to work, but given that it doesn't get used in a lot of the places a default constructor would need to be used, it's a lot more limited in usefuleness, and it could be argued that it would be less error-prone to just create a named factory function for this to make it more obvious that that's what's going on, given how normally MyType() and MyType.init would be identical, whereas they wouldn't be in a type with a static opCall. Certainly, if you're relying on MyType() to be called as the way that your struct is constructed, then you're just asking for trouble. This just gives a way to have a no-arg constructor when you're explicit about it. If you're truly looking for a default constructor, then you need to rethink how your code works.

Also, this idiom doesn't work if you declare any constructors. In that case, you're forced to either declare static opCalls for every constructor you want, or you have to use a factory function for the no-arg constructor instead of a no-arg static opCall so that you can declare actual constructors for the other constructors. If you you declare both a static opCall with no parameters and a constructor, you get an error like this:

q.d(3): Error: struct q.S static opCall is hidden by constructors and can
never be called
q.d(3):        Please use a factory method instead, or replace all
constructors with static opCall.

- Jonathan M Davis

October 30, 2017
On 10/28/17 12:59 PM, LunaticWare wrote:
> Event if there is no default constructor on struct we can still make one that work as well as if it were implemented, here is my example n__n
> 
> ------
> 
> import std.format;
> import std.stdio;
> 
> struct Player
> {
>      string name = "Baz";
>      float[2] position = [0, 0];
> 
>      // Adding an explicit constructor to struct =)
>      // But we can't enforce it since this relies on it =(
>      static ref auto opCall(string name = "Bar", float x = 1, float y = 1)
>      {
>          // Even if we give no argument opCall will still be called ;)
>          writefln("Entering the explicit constructor as '%s'", name);
> 
>          // Taking advantage of the implicit constructor
>          Player self;
> 
>          // Initializing all the members
>          self.name = name;
>          self.position[0] = x;
>          self.position[1] = y;
> 
>          // Returning the reference of the object
>          return self;
>      }
> 
>      string toString()
>      {
>          return format("Hello i am '%s' and at the coordinate x%s / y%s",
>              this.name, this.position[0], this.position[1]);
>      }
> }
> 
> void main()
> {
>      auto foo = Player("Foo", 2.7, 10.6);
>      auto bar = Player();
>      Player baz;
> 
>      writefln("%s\n%s\n%s", foo, bar, baz);
> }
> 
> // == RDMD OUTPUT ==
> // Entering the explicit constructor as 'Foo'
> // Entering the explicit constructor as 'Bar'
> // Hello i am 'Foo' and at the coordinate x2.7 / y10.6
> // Hello i am 'Bar' and at the coordinate x1 / y1
> // Hello i am 'Baz' and at the coordinate x0 / y0
> 

You won't ever get the same support for this as C++. D is very clear that a struct must be constructable from its init value, and be valid.

For instance:

auto p = new Player[1];
assert(p[0].name == "Baz");

-Steve
October 31, 2017
On Monday, 30 October 2017 at 13:24:46 UTC, Steven Schveighoffer wrote:
> On 10/28/17 12:59 PM, LunaticWare wrote:
>> Event if there is no default constructor on struct we can still make one that work as well as if it were implemented, here is my example n__n
>> 
>> ------
>>
> You won't ever get the same support for this as C++. D is very clear that a struct must be constructable from its init value, and be valid.
>
> For instance:
>
> auto p = new Player[1];
> assert(p[0].name == "Baz");
>

I think we can alllow CTFE-able default construction.



October 31, 2017
On 10/31/17 9:49 AM, Dmitry Olshansky wrote:
> On Monday, 30 October 2017 at 13:24:46 UTC, Steven Schveighoffer wrote:
>> On 10/28/17 12:59 PM, LunaticWare wrote:
>>> Event if there is no default constructor on struct we can still make one that work as well as if it were implemented, here is my example n__n
>>>
>>> ------
>>>
>> You won't ever get the same support for this as C++. D is very clear that a struct must be constructable from its init value, and be valid.
>>
>> For instance:
>>
>> auto p = new Player[1];
>> assert(p[0].name == "Baz");
>>
> 
> I think we can allow CTFE-able default construction.
> 

Isn't that what we already have?

-Steve