Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 17, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Attachments:
| Although I agree that having a default constructor would be convenient, I think the problem is that S.init should be known at compile time by the spec. Maybe we could support the following syntax, with a static this instead of this : struct S { int x=11; int y = void; static this() // hypothetical { // x would already be initialized to int.init here assert(x == int.init); // y is left uninitialized here y=x*x; } } On Fri, May 17, 2013 at 2:34 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com > wrote: > On 5/17/13, Walter Bright <walter@digitalmars.com> wrote: > > I oppose this. D has a lot of nice features because of the .init > property. > > Default constructors wreck that. > > Would they? I'm thinking the process would be: > > struct S > { > int x; > int y = void; > > this() // hypothetical > { > // x would already be initialized to int.init here > assert(x == int.init); > > // y is left uninitialized here > } > } > > Maybe that's already clear. But why is .init actually such a big problem? If it becomes arbitrarily expensive to call .init of a struct, well it's because it has to be - if the user really provided an expensive default ctor. But it's entirely the user's responsibility. So then .init can even throw, but throwing exceptions isn't a big deal. Is there some other problem? > > A custom default ctor in a struct is one of the most asked for features. Just yesterday we spent several hours explaining to a C++ user why a default ctor doesn't work, and what .init is for. The whole conversation could have been avoided if D had support for custom default ctors for structs. This topic comes up very often in IRC and the forums. > |
May 17, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timothee Cour | On Friday, 17 May 2013 at 22:45:01 UTC, Timothee Cour wrote:
> Although I agree that having a default constructor would be convenient, I
> think the problem is that S.init should be known at compile time by the
> spec.
>
> Maybe we could support the following syntax, with a static this instead of
> this :
>
> struct S
> {
> int x=11;
> int y = void;
>
> static this() // hypothetical
> {
> // x would already be initialized to int.init here
> assert(x == int.init);
> // y is left uninitialized here
> y=x*x;
> }
> }
>
> On Fri, May 17, 2013 at 2:34 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com
>> wrote:
>
>> On 5/17/13, Walter Bright <walter@digitalmars.com> wrote:
>> > I oppose this. D has a lot of nice features because of the .init
>> property.
>> > Default constructors wreck that.
>>
>> Would they? I'm thinking the process would be:
>>
>> struct S
>> {
>> int x;
>> int y = void;
>>
>> this() // hypothetical
>> {
>> // x would already be initialized to int.init here
>> assert(x == int.init);
>>
>> // y is left uninitialized here
>> }
>> }
>>
>> Maybe that's already clear. But why is .init actually such a big
>> problem? If it becomes arbitrarily expensive to call .init of a
>> struct, well it's because it has to be - if the user really provided
>> an expensive default ctor. But it's entirely the user's
>> responsibility. So then .init can even throw, but throwing exceptions
>> isn't a big deal. Is there some other problem?
>>
>> A custom default ctor in a struct is one of the most asked for
>> features. Just yesterday we spent several hours explaining to a C++
>> user why a default ctor doesn't work, and what .init is for. The whole
>> conversation could have been avoided if D had support for custom
>> default ctors for structs. This topic comes up very often in IRC and
>> the forums.
May be we can allow default ctor, but ensure that it can be
interpreted at compile time and initialize .init value with
ctored value?
Foo.init = Foo(); //somewhere in deep of compiler
But there is one trouble.
struct Foo
{
int[] arr;
this()//can be interpreted at compile time
{
arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
}
}
semantically, all new instances of Foo must get separate instance
of array.
Foo f1;
Foo f2;
assert(f1.arr.ptr !is f2.arr.ptr); //expects put FAILS
However, if Foo.init initialized by compiler with Foo() and f1
and f2 will be initialized with Foo.init, f1.arr and f2.arr will
be the same value.
We can also restrict creating of any mutable reference instances
in this() constructor:
struct Foo
{
int[] arr;
immutable int[] arr2;
this()//can be interpreted at compile time
{
arr = new int[3]; //NG
arr = [1,2,3]; //NG
arr2 = [1,2,3]; //OK, because arr2 is immutable and all
instances of foo can contains an single array instance
}
}
But this way is so difficult and isn't much profitable.
|
May 17, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Igor Stepanov Attachments:
| >> But there is one trouble. I don't see the trouble. struct Foo > { > int[] arr; > this()//can be interpreted at compile time > { > arr = new int[3]; > arr[0] = 1; > arr[1] = 2; > arr[2] = 3; > } > } > semantically, all new instances of Foo must get separate instance of array. Foo f1; > Foo f2; > assert(f1.arr.ptr !is f2.arr.ptr); //expects put FAILS We should have assert(f1.arr.ptr is f2.arr.ptr); as well as assert(f1 is f2); which is consistent with having Foo.init be known at compile time ( we have physical equality, not just logical equality). There's no way around that. So the only question is whether to call the default constructor as static this() or this() (with implicitly knowing that it should be callable at compile time). I think static this() makes it clearer. On Fri, May 17, 2013 at 4:07 PM, Igor Stepanov <wazar.leollone@yahoo.com>wrote: > On Friday, 17 May 2013 at 22:45:01 UTC, Timothee Cour wrote: > >> Although I agree that having a default constructor would be convenient, I think the problem is that S.init should be known at compile time by the spec. >> >> Maybe we could support the following syntax, with a static this instead of this : >> >> struct S >> { >> int x=11; >> int y = void; >> >> static this() // hypothetical >> >> { >> // x would already be initialized to int.init here >> assert(x == int.init); >> // y is left uninitialized here >> y=x*x; >> } >> } >> >> On Fri, May 17, 2013 at 2:34 PM, Andrej Mitrovic < andrej.mitrovich@gmail.com >> >>> wrote: >>> >> >> On 5/17/13, Walter Bright <walter@digitalmars.com> wrote: >>> > I oppose this. D has a lot of nice features because of the > .init >>> property. >>> > Default constructors wreck that. >>> >>> Would they? I'm thinking the process would be: >>> >>> struct S >>> { >>> int x; >>> int y = void; >>> >>> this() // hypothetical >>> { >>> // x would already be initialized to int.init here >>> assert(x == int.init); >>> >>> // y is left uninitialized here >>> } >>> } >>> >>> Maybe that's already clear. But why is .init actually such a big problem? If it becomes arbitrarily expensive to call .init of a struct, well it's because it has to be - if the user really provided an expensive default ctor. But it's entirely the user's responsibility. So then .init can even throw, but throwing exceptions isn't a big deal. Is there some other problem? >>> >>> A custom default ctor in a struct is one of the most asked for features. Just yesterday we spent several hours explaining to a C++ user why a default ctor doesn't work, and what .init is for. The whole conversation could have been avoided if D had support for custom default ctors for structs. This topic comes up very often in IRC and the forums. >>> >> > May be we can allow default ctor, but ensure that it can be > interpreted at compile time and initialize .init value with > ctored value? > Foo.init = Foo(); //somewhere in deep of compiler > > But there is one trouble. > > struct Foo > { > int[] arr; > this()//can be interpreted at compile time > { > arr = new int[3]; > arr[0] = 1; > arr[1] = 2; > arr[2] = 3; > } > } > > semantically, all new instances of Foo must get separate instance of array. > > Foo f1; > Foo f2; > assert(f1.arr.ptr !is f2.arr.ptr); //expects put FAILS > > However, if Foo.init initialized by compiler with Foo() and f1 and f2 will be initialized with Foo.init, f1.arr and f2.arr will be the same value. > > We can also restrict creating of any mutable reference instances > in this() constructor: > > struct Foo > { > int[] arr; > immutable int[] arr2; > this()//can be interpreted at compile time > { > arr = new int[3]; //NG > arr = [1,2,3]; //NG > arr2 = [1,2,3]; //OK, because arr2 is immutable and all > instances of foo can contains an single array instance > > } > } > > But this way is so difficult and isn't much profitable. > > > > |
May 17, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timothee Cour | When programmer see constructor, he think that it will be evaluated each time when he create a new object. This code will seem obvious for any C++ coder. And this coder will be deceived. If we'll add default constructor to structs, we'll must safe of illusion, that constructor is called any time when new object have been created. And reject all cases when we can't provide this illusion. |
May 18, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Igor Stepanov Attachments:
| calling the default ctor static this() removes any such illusion. ---- struct A{ int[]x; static this(){ x=[1,2,3]; } } void main(){ enum a=A.init; static assert(a is A.init); } ---- would work under this proposal. What would be your alternate proposal that would still allow to initialize x to [1,2,3] in the ctor? On Fri, May 17, 2013 at 4:46 PM, Igor Stepanov <wazar.leollone@yahoo.com>wrote: > When programmer see constructor, he think that it will be evaluated each > time when he create a new object. > This code will seem obvious for any C++ coder. > And this coder will be deceived. > > If we'll add default constructor to structs, we'll must safe of illusion, that constructor is called any time when new object have been created. And reject all cases when we can't provide this illusion. > |
May 18, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
On 5/18/13, Timothee Cour <thelastmammoth@gmail.com> wrote:
> S.init should be known at compile time by the spec.
But why is this needed?
|
May 18, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Saturday, 18 May 2013 at 02:34:46 UTC, Andrej Mitrovic wrote:
> On 5/18/13, Timothee Cour <thelastmammoth@gmail.com> wrote:
>> S.init should be known at compile time by the spec.
>
> But why is this needed?
It is needed in any place where such object is created due to default initialization. However if default ctor is CTFEable, dmd can support this feature.
|
May 18, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On Saturday, 18 May 2013 at 05:19:30 UTC, Maxim Fomin wrote:
> On Saturday, 18 May 2013 at 02:34:46 UTC, Andrej Mitrovic wrote:
>> On 5/18/13, Timothee Cour <thelastmammoth@gmail.com> wrote:
>>> S.init should be known at compile time by the spec.
>>
>> But why is this needed?
>
> It is needed in any place where such object is created due to default initialization. However if default ctor is CTFEable, dmd can support this feature.
Another solution is to issue an error when such object isn't initialized explicitely. This isn't very difficult to do.
|
May 18, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Igor Stepanov | On Saturday, May 18, 2013 01:46:16 Igor Stepanov wrote:
> When programmer see constructor, he think that it will be
> evaluated each time when he create a new object.
> This code will seem obvious for any C++ coder.
> And this coder will be deceived.
>
> If we'll add default constructor to structs, we'll must safe of illusion, that constructor is called any time when new object have been created. And reject all cases when we can't provide this illusion.
Also, I really don't think that there's much point in having a default constructor if it's not executed at runtime. If it's going to be known at compile time, then just default initialize all of the members for the init value. What would a default constructor buy you?
It seems to me that a default constructor is useful in cases where you want to do stuff at runtime and the result can differ between executions of the program and possibly between instantions of that object - e.g. grabbing the computer's current IP or setting up the hourglass to display (which is how the hourglass is done in MFC).
And given the advantages of knowing a type's default value at compile time, I just don't see how we can have it be determined at runtime. So, while I think that there are cases where a default constructor could be quite useful, I don't see how we could usefully add it to D given how D deals with default initialization and everything that it does with that.
- Jonathan M Davis
|
May 18, 2013 Re: Struct with default ctor (Was: [dmd-beta] dmd 2.064 beta take 2) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Saturday, 18 May 2013 at 02:34:46 UTC, Andrej Mitrovic wrote:
> On 5/18/13, Timothee Cour <thelastmammoth@gmail.com> wrote:
>> S.init should be known at compile time by the spec.
>
> But why is this needed?
It is quite helpful for template / meta-programming stuff. You are always 100% guaranteed that you can construct S.init and use with your weird template magic wihtout extra checks and fallbacks. However, so far most of real-world usages of T.init I have seen is more about template constraint checks where exact T.init value does not matter that much. Any other usage examples in mind?
|
Copyright © 1999-2021 by the D Language Foundation