www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Explicit default constructor for structs

reply Benjamin Thaut <code benjamin-thaut.de> writes:
Just to be clear, I don't want a default constructor for structs that 
gets called implictly by the compiler, like in C++.

Instead I would really love to have a explicit default constructor. E.g. 
it could look like this (alternative a new keyword "explicit" could be 
introduced, but introduction of new keywords is usually avoided if 
possible, AFAIK):

struct Foo
{
   this(void)
   {
     // do stuff here
   }
}

This default constructor would _never_ be called automatically by the 
compiler. (e.g. when a class is constructed that has struct members.) It 
would only be called in cases where the user explictly calls it.

The following lines would call the explicit default constructor

auto foo1 = Foo();
auto foo2 = new Foo();
foo1 = Foo(); // calls explicit constructor first, then calls assignment 
operator

Whereas the follwing would _not_ call the explicit default constructor.

class Bar
{
   Foo m_foo;
}
auto bar = new Bar();

Foo foo; // does not call the explict default constructor, because there 
is no explicit call here

I think this would fix all cases where you currently wish for a struct 
default constructor in D. Coupeled with " disable this();" you could 
force users to always call one of the struct constructors. Currently I 
work around the issue of not having any default constructors by doing this:

struct DefaultCtor {}; //call default ctor type

enum defaultCtor = DefaultCtor();

struct Foo()
{
    disable this();
   this(DefaultCtor)
   {
     // default constructor
   }

   this(int)
   {
     // other constructor
   }
}

auto foo = Foo(defaultCtor);

While this works, I'm getting anoyed by it every day. For example when 
refactoring types from Classes to Structs and vise versa. As well as 
when placing Classes on the stack using a helper struct. Or when having 
RAII structs that don't take any paramters in their constructor.

What do you think? C&C welcome.

Kind Regards
Benjamin Thaut
Apr 09 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 9 April 2014 at 14:59:35 UTC, Benjamin Thaut wrote:
 Just to be clear, I don't want a default constructor for 
 structs that gets called implictly by the compiler, like in C++.

 Instead I would really love to have a explicit default 
 constructor. E.g. it could look like this (alternative a new 
 keyword "explicit" could be introduced, but introduction of new 
 keywords is usually avoided if possible, AFAIK):

 struct Foo
 {
   this(void)
   {
     // do stuff here
   }
 }

 This default constructor would _never_ be called automatically 
 by the compiler. (e.g. when a class is constructed that has 
 struct members.) It would only be called in cases where the 
 user explictly calls it.

 The following lines would call the explicit default constructor

 auto foo1 = Foo();
 auto foo2 = new Foo();
 foo1 = Foo(); // calls explicit constructor first, then calls 
 assignment operator

 Whereas the follwing would _not_ call the explicit default 
 constructor.

 class Bar
 {
   Foo m_foo;
 }
 auto bar = new Bar();

 Foo foo; // does not call the explict default constructor, 
 because there is no explicit call here

 I think this would fix all cases where you currently wish for a 
 struct default constructor in D. Coupeled with " disable 
 this();" you could force users to always call one of the struct 
 constructors. Currently I work around the issue of not having 
 any default constructors by doing this:

 struct DefaultCtor {}; //call default ctor type

 enum defaultCtor = DefaultCtor();

 struct Foo()
 {
    disable this();
   this(DefaultCtor)
   {
     // default constructor
   }

   this(int)
   {
     // other constructor
   }
 }

 auto foo = Foo(defaultCtor);

 While this works, I'm getting anoyed by it every day. For 
 example when refactoring types from Classes to Structs and vise 
 versa. As well as when placing Classes on the stack using a 
 helper struct. Or when having RAII structs that don't take any 
 paramters in their constructor.

 What do you think? C&C welcome.

 Kind Regards
 Benjamin Thaut
This would be very nice. Yes please.
Apr 09 2014
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 9 April 2014 at 14:59:35 UTC, Benjamin Thaut wrote:
 What do you think? C&C welcome.

 Kind Regards
 Benjamin Thaut
I haven't read though the entire proposal yet (sorry!), but I'm in definite agreement that *something* needs to be done to allow explicit but argument-less construction of structs.
Apr 09 2014
prev sibling next sibling parent reply "Brian Schott" <briancschott gmail.com> writes:
What would this do?

struct SomeStruct
{
     this(int i = 10)
     {
         this.i = i;
     }

     this(void)
     {
         this.i = 20;
     }

     int i;
}

auto s = SomeStruct();
Apr 09 2014
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-09 18:59, Brian Schott wrote:
 What would this do?

 struct SomeStruct
 {
      this(int i = 10)
      {
          this.i = i;
      }

      this(void)
      {
          this.i = 20;
      }

      int i;
 }

 auto s = SomeStruct();
Result in an ambiguity error? -- /Jacob Carlborg
Apr 09 2014
parent reply "Brian Schott" <briancschott gmail.com> writes:
On Wednesday, 9 April 2014 at 17:07:13 UTC, Jacob Carlborg wrote:
 Result in an ambiguity error?
Really? What does this program print using a current version of DMD? import std.stdio; struct SomeStruct { this(int i = 10) { this.i = i; } int i; } void main(string[] args) { auto s = SomeStruct(); writeln("s.i = ", s.i); } I don't think it would be ambiguous at all :-)
Apr 09 2014
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2014-04-09 19:10, Brian Schott wrote:

 Really? What does this program print using a current version of DMD?

 import std.stdio;

 struct SomeStruct
 {
      this(int i = 10)
      {
          this.i = i;
      }
      int i;
 }

 void main(string[] args)
 {
      auto s = SomeStruct();
      writeln("s.i = ", s.i);
 }

 I don't think it would be ambiguous at all :-)
Yeah, because currently DMD doesn't have the proposed feature. If it's added I can imagine it's similar to writing this: void foo (); void foo (int i = 0); -- /Jacob Carlborg
Apr 09 2014
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/9/14, Brian Schott <briancschott gmail.com> wrote:
 Really? What does this program print using a current version of
 DMD?

 import std.stdio;

 struct SomeStruct
 {
 	this(int i = 10)
 	{
 		this.i = i;
 	}
 	int i;
 }

 void main(string[] args)
 {
 	auto s = SomeStruct();
 	writeln("s.i = ", s.i);
 }
This is a current bug that is going to be fixed: https://github.com/D-Programming-Language/dmd/pull/1397
Apr 10 2014
parent reply "Remo" <remo4d gmail.com> writes:
On Thursday, 10 April 2014 at 11:39:16 UTC, Andrej Mitrovic wrote:
 On 4/9/14, Brian Schott <briancschott gmail.com> wrote:
 Really? What does this program print using a current version of
 DMD?

 import std.stdio;

 struct SomeStruct
 {
 	this(int i = 10)
 	{
 		this.i = i;
 	}
 	int i;
 }

 void main(string[] args)
 {
 	auto s = SomeStruct();
 	writeln("s.i = ", s.i);
 }
This is a current bug that is going to be fixed: https://github.com/D-Programming-Language/dmd/pull/1397
Please do not forget about C++ porting problems that are related to this. The code from C++ should compile and work as expected or does not compile at all and give meaningful error message. Right now it compiles but does not work at all. This struct constructor problem is one of the ground why I have stopped porting code to D. I hope there will be proper solution soon.
Apr 10 2014
parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-10 17:21, Remo wrote:

 Please do not forget about C++ porting problems that are related to this.
 The code from C++ should compile and work as expected or does not
 compile at all and give meaningful error message.
 Right now it compiles but does not work at all.
 This struct constructor problem is one of the ground why I have stopped
 porting code to D.
 I hope there will be proper solution soon.
How said anything about that? It has been said that one should be able to paste C code in a D file and have it compile with the same resulting semantics as in C or not compile at all. But never for C++. -- /Jacob Carlborg
Apr 10 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 10 April 2014 at 19:28:16 UTC, Jacob Carlborg wrote:
 On 2014-04-10 17:21, Remo wrote:

 Please do not forget about C++ porting problems that are 
 related to this.
 The code from C++ should compile and work as expected or does 
 not
 compile at all and give meaningful error message.
 Right now it compiles but does not work at all.
 This struct constructor problem is one of the ground why I 
 have stopped
 porting code to D.
 I hope there will be proper solution soon.
How said anything about that? It has been said that one should be able to paste C code in a D file and have it compile with the same resulting semantics as in C or not compile at all. But never for C++.
Well, it's true that the idea is that you can copy paste C code into D and it "just works", keeping the same semantics (provided minor/trivial tweaks). And nobody ever sold you could do the same thing with C++. *BUT*, if you happen to copy paste C++ code, and it *does* compile, then it is pretty much expected to keep the same resulting semantics, yes. The "this(Arg arg = someDefault)" is a flagrant example of something that should be rejected. Not only because it's stupid to write in plain D, but also because it creates gratuitous deviation from the behavior you'd get in C++. And that's actually very bad (IMO).
Apr 10 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"monarch_dodra"  wrote in message 
news:rftskgfoeuvyeuvrusei forum.dlang.org...

 *BUT*, if you happen to copy paste C++ code, and it *does* compile, then 
 it is pretty much expected to keep the same resulting semantics, yes.
These expectations will lead to disappointment.
Apr 11 2014
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, April 11, 2014 22:38:28 Daniel Murphy wrote:
 "monarch_dodra"  wrote in message
 news:rftskgfoeuvyeuvrusei forum.dlang.org...
 
 *BUT*, if you happen to copy paste C++ code, and it *does* compile, then
 it is pretty much expected to keep the same resulting semantics, yes.
These expectations will lead to disappointment.
One of the goals of D was to make it so that when _C_ code was compiled as D code, it either wouldn't compile or would have identical semantics, and I believe that that is still true save for a very short list of exceptions (the only ones that come to mind are that the calling conventions wouldn't be the same and that static arrays are value types in D whereas they're reference types in C). However, that's not at all true for C++. You're probably more likely to be able to port Java code directly and have it have the same semantics than C++ code. A shining example of that is the semantics for variables of class types. In C++, if they're not declared as pointers, then they're value types, whereas they're always reference types in D. Part of the whole point of D is to have better semantics than C++, so it's certainly not going to try and keep the same semantics as C++. For the most part, we haven't gratuitously changed the semantics, but there are a lot of places where we gained something by changing them, so we did. - Jonathan M Davis
Apr 11 2014
prev sibling parent reply "Remo" <remo4d gmail.com> writes:
On Friday, 11 April 2014 at 12:38:14 UTC, Daniel Murphy wrote:
 "monarch_dodra"  wrote in message 
 news:rftskgfoeuvyeuvrusei forum.dlang.org...

 *BUT*, if you happen to copy paste C++ code, and it *does* 
 compile, then it is pretty much expected to keep the same 
 resulting semantics, yes.
These expectations will lead to disappointment.
Why everyone here seems to confuse portion with copy and paste? Of course C++ code that is just copy and pasted will not work or not work as expected. But I think (hope) that one of the advantage of D is that it allow to easily PORT C/C++ code. If this is not the case and was really not intended then it is probably better to use C++14 instate. Other advantage of D could be easy interconnection of C/C++ libraries and D...
Apr 11 2014
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, April 11, 2014 17:00:50 Remo wrote:
 On Friday, 11 April 2014 at 12:38:14 UTC, Daniel Murphy wrote:
 "monarch_dodra" wrote in message
 news:rftskgfoeuvyeuvrusei forum.dlang.org...
 
 *BUT*, if you happen to copy paste C++ code, and it *does*
 compile, then it is pretty much expected to keep the same
 resulting semantics, yes.
These expectations will lead to disappointment.
Why everyone here seems to confuse portion with copy and paste? Of course C++ code that is just copy and pasted will not work or not work as expected. But I think (hope) that one of the advantage of D is that it allow to easily PORT C/C++ code. If this is not the case and was really not intended then it is probably better to use C++14 instate. Other advantage of D could be easy interconnection of C/C++ libraries and D...
How easy it is to port C++ to D depends on what the code does. Some styles of code and types of operations will port over very easily, whereas others would require a fair bit of refactoring. For the most part, the changes that you'd be forced to make would be for the better, but if a lot of your code is doing stuff that doesn't port easily, then it could be painful to port. Personally, I'd probably rewrite the code in D and just use the C++ as a reference rather than trying to really port it. - Jonathan M Davis
Apr 11 2014
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 10 April 2014 at 21:23:43 UTC, monarch_dodra wrote:>
 *BUT*, if you happen to copy paste C++ code, and it *does* 
 compile, then it is pretty much expected to keep the same 
 resulting semantics, yes.
It does not work that way and has never worked. Think about class semantics for example.
Apr 11 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 11 April 2014 at 12:58:09 UTC, Dicebot wrote:
 On Thursday, 10 April 2014 at 21:23:43 UTC, monarch_dodra 
 wrote:>
 *BUT*, if you happen to copy paste C++ code, and it *does* 
 compile, then it is pretty much expected to keep the same 
 resulting semantics, yes.
It does not work that way and has never worked. Think about class semantics for example.
Yeah. It'd say those wouldn't compile anyway, but I guess something as trivial as: //---- class A {...} A a; a.doit; //---- Would compile for both languages, but give different results. Fine.
Apr 11 2014
parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-11 15:53, monarch_dodra wrote:

 Yeah. It'd say those wouldn't compile anyway, but I guess something as
 trivial as:
 //----
 class A
 {...}
 A a;
 a.doit;
 //----
 Would compile for both languages, but give different results.

 Fine.
Unless "doit" is non-virtual in both versions. -- /Jacob Carlborg
Apr 11 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 11 April 2014 at 15:54:36 UTC, Jacob Carlborg wrote:
 On 2014-04-11 15:53, monarch_dodra wrote:

 Yeah. It'd say those wouldn't compile anyway, but I guess 
 something as
 trivial as:
 //----
 class A
 {...}
 A a;
 a.doit;
 //----
 Would compile for both languages, but give different results.

 Fine.
Unless "doit" is non-virtual in both versions.
Why? The D version would just go from "object.Error Access Violation" to "AssertError null this". And in release, you'd still (highly probably) still get the Access Violation.
Apr 11 2014
next sibling parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"monarch_dodra"  wrote in message 
news:ktbdlcaqahsqmwkiddvc forum.dlang.org...

 Why? The D version would just go from "object.Error Access Violation" to 
 "AssertError null this".

 And in release, you'd still (highly probably) still get the Access 
 Violation.
Sadly I've encountered C++ code that deliberately calls member functions on null class pointers.
Apr 11 2014
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 12, 2014 02:26:54 Daniel Murphy wrote:
 "monarch_dodra"  wrote in message
 news:ktbdlcaqahsqmwkiddvc forum.dlang.org...
 
 Why? The D version would just go from "object.Error Access Violation" to
 "AssertError null this".
 
 And in release, you'd still (highly probably) still get the Access
 Violation.
Sadly I've encountered C++ code that deliberately calls member functions on null class pointers.
I've never seen code that it did it on purpose, but I've certainly seen code that did it on accident. And what's really fun is when it's non-virtual, because that won't segfault on the call - only when it does something inside the function which causes the this pointer to be dereferenced (e.g accessing a member variable or virtual member function). _That_ can really confuse people when it happens. At one point at work, we had a class that was never instantiated but worked great (it really didn't need to be a class at all, just free functions, as it didn't actually have any member variables). Fortunately, I'd seen the problem before and could explain to the others once I remembered, but no one else on the team had ever seen anything like it and all found it quite surprising. _I_ was certainly shocked by it when I originally ran into it - though it all makes sense when you look at what the compiler needs to do when calling a function. - Jonathan M Davis
Apr 11 2014
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-11 18:05, monarch_dodra wrote:

 Why? The D version would just go from "object.Error Access Violation" to
 "AssertError null this".
Hmm, I was pretty sure it wouldn't assert.
 And in release, you'd still (highly probably) still get the Access
 Violation.
No, in release mode it's possible to call non-virtual methods on null references. -- /Jacob Carlborg
Apr 11 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 11 April 2014 at 20:36:12 UTC, Jacob Carlborg wrote:
 On 2014-04-11 18:05, monarch_dodra wrote:

 Why? The D version would just go from "object.Error Access 
 Violation" to
 "AssertError null this".
Hmm, I was pretty sure it wouldn't assert.
 And in release, you'd still (highly probably) still get the 
 Access
 Violation.
No, in release mode it's possible to call non-virtual methods on null references.
Right, the call will succeed, but if the function accesses any class members, it will access violation *there*. Hence the "highly likely".
Apr 11 2014
parent Jacob Carlborg <doob me.com> writes:
On 2014-04-11 22:48, monarch_dodra wrote:

 Right, the call will succeed, but if the function accesses any class
 members, it will access violation *there*. Hence the "highly likely".
Yeah, right. -- /Jacob Carlborg
Apr 12 2014
prev sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 09.04.2014 18:59, schrieb Brian Schott:
 What would this do?

 struct SomeStruct
 {
      this(int i = 10)
      {
          this.i = i;
      }

      this(void)
      {
          this.i = 20;
      }

      int i;
 }

 auto s = SomeStruct();
Thats easy to answer. What would it do if you replace the "struct" with "class" and the "void" with nothing?
Apr 09 2014
parent reply "Brian Schott" <briancschott gmail.com> writes:
On Wednesday, 9 April 2014 at 18:47:41 UTC, Benjamin Thaut wrote:
 Thats easy to answer. What would it do if you replace the 
 "struct" with "class" and the "void" with nothing?
This thread is giving me some fun ideas for static analysis rules.
Apr 09 2014
next sibling parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 09.04.2014 20:53, schrieb Brian Schott:
 On Wednesday, 9 April 2014 at 18:47:41 UTC, Benjamin Thaut wrote:
 Thats easy to answer. What would it do if you replace the "struct"
 with "class" and the "void" with nothing?
This thread is giving me some fun ideas for static analysis rules.
Just saying, if you do the same with a class, the default constructor is picked and not the one with the default argument. So it should do the same for structs.
Apr 09 2014
prev sibling parent "Brian Schott" <briancschott gmail.com> writes:
On Wednesday, 9 April 2014 at 18:53:20 UTC, Brian Schott wrote:
 On Wednesday, 9 April 2014 at 18:47:41 UTC, Benjamin Thaut 
 wrote:
 Thats easy to answer. What would it do if you replace the 
 "struct" with "class" and the "void" with nothing?
This thread is giving me some fun ideas for static analysis rules.
As of a minute ago D-Scanner will warn about the following code: class TestClass { this() { i = 10; } this(int i = 20) { this.i = i; } int i; } struct Bogus { this(int x = 0) {} } test.d(1:7)[warn]: This class has a zero-argument constructor as well as a constructor with one default argument. This can be confusing test.d(10:2)[warn]: This struct constructor can never be called with its default argument.
Apr 09 2014
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2014-04-09 16:59, Benjamin Thaut wrote:
 Just to be clear, I don't want a default constructor for structs that
 gets called implictly by the compiler, like in C++.

 Instead I would really love to have a explicit default constructor. E.g.
 it could look like this (alternative a new keyword "explicit" could be
 introduced, but introduction of new keywords is usually avoided if
 possible, AFAIK):

 struct Foo
 {
    this(void)
    {
      // do stuff here
    }
 }

 This default constructor would _never_ be called automatically by the
 compiler. (e.g. when a class is constructed that has struct members.) It
 would only be called in cases where the user explictly calls it.

 The following lines would call the explicit default constructor

 auto foo1 = Foo();
 auto foo2 = new Foo();
 foo1 = Foo(); // calls explicit constructor first, then calls assignment
 operator
What's the advantage over using a static opCall, that it works with "new"? -- /Jacob Carlborg
Apr 09 2014
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 09.04.2014 19:05, schrieb Jacob Carlborg:
 What's the advantage over using a static opCall, that it works with "new"?
That you can use it together with disable this();
Apr 09 2014
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2014 04:59 PM, Benjamin Thaut wrote:
 Instead I would really love to have a explicit default constructor. E.g.
 it could look like this (alternative a new keyword "explicit" could be
 introduced, but introduction of new keywords is usually avoided if
 possible, AFAIK):

 struct Foo
 {
    this(void)
    {
      // do stuff here
    }
 }
Why not just: struct Foo{ this(){ // do stuff here } } void main(){ Foo foo1; // error, no init value auto foo2=Foo(); // ok }
Apr 09 2014
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 09.04.2014 20:33, schrieb Timon Gehr:
 On 04/09/2014 04:59 PM, Benjamin Thaut wrote:
 Why not just:

 struct Foo{
      this(){
          // do stuff here
      }
 }

 void main(){
      Foo foo1; // error, no init value
      auto foo2=Foo(); // ok
 }
Because then the user might think, that the default constructor gets called implicitly by the compiler. Just like in C++. But as that is not the case the syntax should be different to indicate that a struct might still be instaniated just using T.init. Kind Regards Benjamin Thaut
Apr 09 2014
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/09/2014 08:53 PM, Benjamin Thaut wrote:
 Am 09.04.2014 20:33, schrieb Timon Gehr:
 On 04/09/2014 04:59 PM, Benjamin Thaut wrote:
 Why not just:

 struct Foo{
      this(){
          // do stuff here
      }
 }

 void main(){
      Foo foo1; // error, no init value
      auto foo2=Foo(); // ok
 }
Because then the user might think, that the default constructor gets called implicitly by the compiler.
This would be pointed out by the compiler. (i.e. it is an error instead of an implicit call.)
 Just like in C++. But as that is not
 the case the syntax should be different to indicate that a struct might
 still be instaniated just using T.init.

 Kind Regards
 Benjamin Thaut
What would be an use case for a bypassable default constructor?
Apr 09 2014
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 09.04.2014 21:02, schrieb Timon Gehr:
 On 04/09/2014 08:53 PM, Benjamin Thaut wrote:
 Am 09.04.2014 20:33, schrieb Timon Gehr:
 On 04/09/2014 04:59 PM, Benjamin Thaut wrote:
 Why not just:

 struct Foo{
      this(){
          // do stuff here
      }
 }

 void main(){
      Foo foo1; // error, no init value
      auto foo2=Foo(); // ok
 }
Because then the user might think, that the default constructor gets called implicitly by the compiler.
This would be pointed out by the compiler. (i.e. it is an error instead of an implicit call.)
 Just like in C++. But as that is not
 the case the syntax should be different to indicate that a struct might
 still be instaniated just using T.init.

 Kind Regards
 Benjamin Thaut
What would be an use case for a bypassable default constructor?
I don't know any use case. But AFAIK the reason there is no default constructor for structs in D has to do something with exception safetey. So whatever cases those are, they might need a bypassable default constructor.
Apr 09 2014
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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();
Apr 09 2014
next sibling parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 09.04.2014 20:42, schrieb Walter Bright:
 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();
But I don't want the construction to be syntacically any different. I know there are workarounds, but after all they are workarounds.
Apr 09 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
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...
Apr 10 2014
next sibling parent "Atila Neves" <atila.neves gmail.com> writes:
+1

Atila

 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...
Apr 10 2014
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 10 April 2014 at 11:13:45 UTC, monarch_dodra wrote:
 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();
And they are all broken in their own ways.
Apr 27 2014
prev sibling parent reply "ketmar" <ketmar ketmar.no-ip.org> writes:
On Wednesday, 9 April 2014 at 14:59:35 UTC, Benjamin Thaut wrote:
 E.g. it could look like this (alternative a new keyword 
 "explicit" could be introduced, but introduction of new 
 keywords is usually avoided if possible, AFAIK):
sorry for not reading the whole post and necroposting, but please, please, please vote for new keywords! please, stop suggesting obscure features that cannot be logicaly deducted! ' explicit' attribute can work fine here, and 'this(void)' is impossible to understand without carefull *studying* the documentation. and it is really easy to miss when reading the code.
Apr 26 2014
parent "Temtaime" <temtaime gmail.com> writes:
People, why you hates ctors for structs ?

"Default ctor" - simple a workaround.
Just allow ctors with structs and it's all.
Apr 27 2014