www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - hacky way to get explicit default constructor on struct :P

reply LunaticWare <exemple gmail.com> writes:
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
Oct 28 2017
next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Oct 28 2017
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Oct 30 2017
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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.
Oct 31 2017
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Oct 31 2017