Passing parameter when creating object array
Chris Nicholson-Sauls
ibisbasenji at gmail.com
Tue Aug 7 14:22:50 PDT 2007
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
More information about the Digitalmars-d-learn
mailing list