Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 07, 2007 Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error: Myclass x (10)[50] I don't want to have to do: Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on Does D support the more intuitive Myclass x (10)[50] mechanism? |
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel White | "Daniel White" <twinbee41@skytopia.com> wrote in message news:f98h52$7bj$1@digitalmars.com... > I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error: > > Myclass x (10)[50] > > I don't want to have to do: > > Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on > > Does D support the more intuitive Myclass x (10)[50] mechanism? D doesn't support instantiating an array of instances of classes in one statement in any way, so.. no. |
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel White | Daniel White wrote:
> I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error:
>
> Myclass x (10)[50]
>
> I don't want to have to do:
>
> Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on
>
> Does D support the more intuitive Myclass x (10)[50] mechanism?
C++ has a library type for arrays, where you can write
std::vector<MyClass> x(50, MyClass(10));
D tends to prefer pushing this kind of thing out of the library and into the language, but maybe somebody can point out the D library solution for this.
-- James
|
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to James Dennett | James Dennett wrote:
> Daniel White wrote:
>> I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error:
>>
>> Myclass x (10)[50]
>>
>> I don't want to have to do:
>>
>> Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on
>>
>> Does D support the more intuitive Myclass x (10)[50] mechanism?
>
> C++ has a library type for arrays, where you can write
>
> std::vector<MyClass> x(50, MyClass(10));
>
> D tends to prefer pushing this kind of thing out of the library
> and into the language, but maybe somebody can point out the D
> library solution for this.
>
> -- James
Its straightforward:
T[] populateArray (T) (int len, lazy T ctor) {
T[] result = new T[len];
foreach (inout elem; result) {
elem = ctor();
}
return result;
}
Usage is like so:
auto array = populateArray(50, new MyClass(10));
This also works fine with structures, and technically any other type. Although its inefficient for basic scalars, for that use a slice-assignment:
int[] arr1 = new int[50]; arr1[] = 10;
int[50] arr2; arr2[] = 10;
-- Chris Nicholson-Sauls
|
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | Chris Nicholson-Sauls wrote: > James Dennett wrote: >> Daniel White wrote: >>> I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error: >>> >>> Myclass x (10)[50] >>> >>> I don't want to have to do: >>> >>> Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on >>> >>> Does D support the more intuitive Myclass x (10)[50] mechanism? >> >> C++ has a library type for arrays, where you can write >> >> std::vector<MyClass> x(50, MyClass(10)); >> >> D tends to prefer pushing this kind of thing out of the library >> and into the language, but maybe somebody can point out the D >> library solution for this. >> >> -- James > > Its straightforward: > > T[] populateArray (T) (int len, lazy T ctor) { > T[] result = new T[len]; > > foreach (inout elem; result) { > elem = ctor(); > } > return result; > } > > > Usage is like so: > > auto array = populateArray(50, new MyClass(10)); > > > > This also works fine with structures, and technically any other type. Although its inefficient for basic scalars, for that use a slice-assignment: > > int[] arr1 = new int[50]; arr1[] = 10; > int[50] arr2; arr2[] = 10; > > > -- Chris Nicholson-Sauls Using new on a dynamic array type already allows you to pass something looking like a constructor call: auto a = new int[](50); // An array of 50 elements It might be appropriate to add a second, optional parameter to this constructor, with the array's default initializer: auto b = new int[](50, 5); // An array of 50 5s This implies that, for arrays of class references, saying this auto c = new Foo[](10, new Foo); would result in an array of 10 references to the same instance of Foo. I believe that any other behavior would be surprising. Therefore, some notation must be provided for allocating an array and not initializing its contents, which would allow something like your lazy initializer above to operate without initializing the array's contents first. A number of ideas occur to me; the simplest is perhaps an optional argument to 'new' itself: auto d = new(false) Foo[](10); // Allocate array, don't initialize it. All of this being said, I am not sure how serious of an issue this really is. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > Using new on a dynamic array type already allows you to pass something looking like a constructor call: > > auto a = new int[](50); // An array of 50 elements > > It might be appropriate to add a second, optional parameter to this constructor, with the array's default initializer: > > auto b = new int[](50, 5); // An array of 50 5s > This syntax is already taken, for allocating nested arrays: http://www.digitalmars.com/d/expression.html#NewExpression -- Remove ".doesnotlike.spam" from the mail address. |
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote:
> Chris Nicholson-Sauls wrote:
>> James Dennett wrote:
>>> Daniel White wrote:
>>>> I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error:
>>>>
>>>> Myclass x (10)[50]
>>>>
>>>> I don't want to have to do:
>>>>
>>>> Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on
>>>>
>>>> Does D support the more intuitive Myclass x (10)[50] mechanism?
>>>
>>> C++ has a library type for arrays, where you can write
>>>
>>> std::vector<MyClass> x(50, MyClass(10));
>>>
>>> D tends to prefer pushing this kind of thing out of the library
>>> and into the language, but maybe somebody can point out the D
>>> library solution for this.
>>>
>>> -- James
>>
>> Its straightforward:
>>
>> T[] populateArray (T) (int len, lazy T ctor) {
>> T[] result = new T[len];
>>
>> foreach (inout elem; result) {
>> elem = ctor();
>> }
>> return result;
>> }
>>
>>
>> Usage is like so:
>>
>> auto array = populateArray(50, new MyClass(10));
>>
>>
>>
>> This also works fine with structures, and technically any other type. Although its inefficient for basic scalars, for that use a slice-assignment:
>>
>> int[] arr1 = new int[50]; arr1[] = 10;
>> int[50] arr2; arr2[] = 10;
>>
>>
>> -- Chris Nicholson-Sauls
>
> Using new on a dynamic array type already allows you to pass something looking like a constructor call:
>
> auto a = new int[](50); // An array of 50 elements
>
> It might be appropriate to add a second, optional parameter to this constructor, with the array's default initializer:
>
> auto b = new int[](50, 5); // An array of 50 5s
>
> This implies that, for arrays of class references, saying this
>
> auto c = new Foo[](10, new Foo);
>
> would result in an array of 10 references to the same instance of Foo. I believe that any other behavior would be surprising.
>
> Therefore, some notation must be provided for allocating an array and not initializing its contents, which would allow something like your lazy initializer above to operate without initializing the array's contents first. A number of ideas occur to me; the simplest is perhaps an optional argument to 'new' itself:
>
> auto d = new(false) Foo[](10); // Allocate array, don't initialize it.
>
> All of this being said, I am not sure how serious of an issue this really is.
>
Hmm. That could be rather dangerous, actually. So here's another thought. Let's get 'new int[5][10][15]' working, then redefine the trailing parentheses to specify an initializor, and then furthermore make that initializor lazy anytime it is more complex than a literal or symbol, possibly including 'symbol.symbol' as field reads.
auto array = new MyClass[50](new MyClass(10));
You know, now that I actually see it... I'm not so fond of it.
But honestly, I don't think the cost is worth worrying too much about. I ran a quick test timing my function above against a simple foreach over an pre-allocated array. The 'populate' function averaged only 10 microseconds slower. I, for one, can handle 10 millionths of almost anything. :)
-- Chris Nicholson-Sauls
|
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | Chris Nicholson-Sauls wrote:
> Kirk McDonald wrote:
>> Chris Nicholson-Sauls wrote:
>>> James Dennett wrote:
>>>> Daniel White wrote:
>>>>> I've just found out from elsewhere that it's not possible in C++ to create an array of objects whilst simultaneously passing a parameter to the constructor of each of those objects. Something like this returns an error:
>>>>>
>>>>> Myclass x (10)[50]
>>>>>
>>>>> I don't want to have to do:
>>>>>
>>>>> Myclass x[5] = {10,10,10,10,10,10.................} // ...and so on
>>>>>
>>>>> Does D support the more intuitive Myclass x (10)[50] mechanism?
>>>>
>>>> C++ has a library type for arrays, where you can write
>>>>
>>>> std::vector<MyClass> x(50, MyClass(10));
>>>>
>>>> D tends to prefer pushing this kind of thing out of the library
>>>> and into the language, but maybe somebody can point out the D
>>>> library solution for this.
>>>>
>>>> -- James
>>>
>>> Its straightforward:
>>>
>>> T[] populateArray (T) (int len, lazy T ctor) {
>>> T[] result = new T[len];
>>>
>>> foreach (inout elem; result) {
>>> elem = ctor();
>>> }
>>> return result;
>>> }
>>>
>>>
>>> Usage is like so:
>>>
>>> auto array = populateArray(50, new MyClass(10));
>>>
>>>
>>>
>>> This also works fine with structures, and technically any other type. Although its inefficient for basic scalars, for that use a slice-assignment:
>>>
>>> int[] arr1 = new int[50]; arr1[] = 10;
>>> int[50] arr2; arr2[] = 10;
>>>
>>>
>>> -- Chris Nicholson-Sauls
>>
>> Using new on a dynamic array type already allows you to pass something looking like a constructor call:
>>
>> auto a = new int[](50); // An array of 50 elements
>>
>> It might be appropriate to add a second, optional parameter to this constructor, with the array's default initializer:
>>
>> auto b = new int[](50, 5); // An array of 50 5s
>>
>> This implies that, for arrays of class references, saying this
>>
>> auto c = new Foo[](10, new Foo);
>>
>> would result in an array of 10 references to the same instance of Foo. I believe that any other behavior would be surprising.
>>
>> Therefore, some notation must be provided for allocating an array and not initializing its contents, which would allow something like your lazy initializer above to operate without initializing the array's contents first. A number of ideas occur to me; the simplest is perhaps an optional argument to 'new' itself:
>>
>> auto d = new(false) Foo[](10); // Allocate array, don't initialize it.
>>
>> All of this being said, I am not sure how serious of an issue this really is.
>>
>
> Hmm. That could be rather dangerous, actually. So here's another thought. Let's get 'new int[5][10][15]' working, then redefine the trailing parentheses to specify an initializor, and then furthermore make that initializor lazy anytime it is more complex than a literal or symbol, possibly including 'symbol.symbol' as field reads.
>
> auto array = new MyClass[50](new MyClass(10));
>
> You know, now that I actually see it... I'm not so fond of it.
>
> But honestly, I don't think the cost is worth worrying too much about. I ran a quick test timing my function above against a simple foreach over an pre-allocated array. The 'populate' function averaged only 10 microseconds slower. I, for one, can handle 10 millionths of almost anything. :)
>
> -- Chris Nicholson-Sauls
Oh yes, I should probably also mention that my test program was creating arrays of 1000 objects -- not just 50. :) So for use cases such as in the OP, the difference is utterly insignificant.
-- Chris Nicholson-Sauls
|
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Deewiant | Deewiant wrote: > Kirk McDonald wrote: > >>Using new on a dynamic array type already allows you to pass something >>looking like a constructor call: >> >>auto a = new int[](50); // An array of 50 elements >> >>It might be appropriate to add a second, optional parameter to this >>constructor, with the array's default initializer: >> >>auto b = new int[](50, 5); // An array of 50 5s >> > > > This syntax is already taken, for allocating nested arrays: > http://www.digitalmars.com/d/expression.html#NewExpression > It could still work. Nested (or un-nested) dynamic array types would have two constructors: The existing ones, for defining the size of the array, and one with one additional argument, defining the default initializer of the innermost array's elements. Therefore: new char[][](10) // allocate an array of 10 strings new char[][](10, 20) // allocate 10 strings of 20 \0 characters new char[][](10, 20, 'a') // allocate 10 strings of 20 'a's. But now I'm having trouble understanding another part of that page: "If there is a new ( ArgumentList ), then those arguments are passed to the class or struct specific allocator function after the size argument." For classes, saying 'new C[](20)' creates an array of 20 class /references/, set to null, and the class's allocator is never called. For structs, it is not the structs themselves being new'ed. A struct's allocator overload is used when you say 'new S', which returns an S*. Saying 'new S[](20)' will create an array whose size in bytes is S.sizeof * 20. The struct's allocator has nothing to do with it. Creating an array of type S*[] has basically the same issue as an array of class references: The pointers are initialized to null, and the struct's allocator is never called. Therefore, this line in the spec appears to be useless, and my new(false) suggestion could still work. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
August 07, 2007 Re: Passing parameter when creating object array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | Chris Nicholson-Sauls wrote: >> But honestly, I don't think the cost is worth worrying too much about. I ran a quick test timing my function above against a simple foreach over an pre-allocated array. The 'populate' function averaged only 10 microseconds slower. I, for one, can handle 10 millionths of almost anything. :) >> >> -- Chris Nicholson-Sauls > > > Oh yes, I should probably also mention that my test program was creating arrays of 1000 objects -- not just 50. :) So for use cases such as in the OP, the difference is utterly insignificant. > > -- Chris Nicholson-Sauls Hence why I said I wasn't sure how serious of an issue this is. :-) -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
Copyright © 1999-2021 by the D Language Foundation