Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 10, 2013 Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Hi, I'm new to the D programming language. Overall I'm liking things very much, but I'm still getting the hang of a few things. Here's a basic programming pattern: I have a class called Thing, and while I'm coding I decide I need N Thing instances. In C++ that's a matter of std::vector<Thing> things(N); In python, I can use a list comprehension. things = [Thing() for _ in range(N)] However, the obvious D version doesn't work. auto things = new Thing[N]; Because Thing.init is null, this produces an array of null references. Of course, I can write a for loop to fill in the array after creation, but this feels very un-D-like. Is there a straightforward way to create a bunch of class instances? |
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon | On Sunday, 10 February 2013 at 06:14:37 UTC, Simon wrote:
> Hi, I'm new to the D programming language. Overall I'm liking
> things very much, but I'm still getting the hang of a few things.
>
> Here's a basic programming pattern: I have a class called Thing,
> and while I'm coding I decide I need N Thing instances.
>
> In C++ that's a matter of
>
> std::vector<Thing> things(N);
>
> In python, I can use a list comprehension.
>
> things = [Thing() for _ in range(N)]
>
> However, the obvious D version doesn't work.
>
> auto things = new Thing[N];
>
> Because Thing.init is null, this produces an array of null
> references. Of course, I can write a for loop to fill in the
> array after creation, but this feels very un-D-like. Is there a
> straightforward way to create a bunch of class instances?
You can create separate function which fills array with instances and return it. You can make Thing a struct aliased to array of classes which again initializes properly in constructor an array. But then you should take care that struct constructor is called.
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon | On 02/09/2013 10:14 PM, Simon wrote:
> Hi, I'm new to the D programming language. Overall I'm liking
> things very much, but I'm still getting the hang of a few things.
>
> Here's a basic programming pattern: I have a class called Thing,
> and while I'm coding I decide I need N Thing instances.
>
> In C++ that's a matter of
>
> std::vector<Thing> things(N);
>
> In python, I can use a list comprehension.
>
> things = [Thing() for _ in range(N)]
>
> However, the obvious D version doesn't work.
>
> auto things = new Thing[N];
>
> Because Thing.init is null, this produces an array of null
> references. Of course, I can write a for loop to fill in the
> array after creation, but this feels very un-D-like. Is there a
> straightforward way to create a bunch of class instances?
Here is one way:
import std.stdio;
import std.range;
import std.algorithm;
class Thing
{
int i;
this(int i)
{
this.i = i;
}
}
void main()
{
auto things = iota(10).map!(i => new Thing(i))().array;
}
Ali
--
D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 02/09/2013 10:52 PM, Ali Çehreli wrote: > auto things = iota(10).map!(i => new Thing(i))().array; Actually, without the extra parentheses: auto things = iota(10).map!(i => new Thing(i)).array; Ali |
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 10 February 2013 at 06:57:42 UTC, Ali Çehreli wrote:
> On 02/09/2013 10:52 PM, Ali Çehreli wrote:
>
> > auto things = iota(10).map!(i => new Thing(i))().array;
>
> Actually, without the extra parentheses:
>
> auto things = iota(10).map!(i => new Thing(i)).array;
>
> Ali
It's a shame there isn't any simple syntax for it, but that's some neat and flexible code.
Thanks!
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon | On Sun, Feb 10, 2013 at 8:40 AM, Simon <none@example.org> wrote:
>> auto things = iota(10).map!(i => new Thing(i)).array;
>>
>> Ali
>
>
> It's a shame there isn't any simple syntax for it, but that's some neat and flexible code.
Oh, you can easily use a template:
import std.array;
import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
class Thing
{
int i;
this(int i)
{
this.i = i;
}
void toString(scope void delegate(const(char)[]) sink) const
{
sink("Thing: " ~ to!string(i));
}
}
/// Helper template
What[] makeArray(alias What)(size_t size)
{
return iota(size).map!(i => new What(i)).array;
}
void main()
{
auto things = makeArray!(Thing)(10);
writeln(things);
}
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon | On 10-2-2013 7:14, Simon wrote:
> Hi, I'm new to the D programming language. Overall I'm liking
> things very much, but I'm still getting the hang of a few things.
>
> Here's a basic programming pattern: I have a class called Thing,
> and while I'm coding I decide I need N Thing instances.
>
> In C++ that's a matter of
>
> std::vector<Thing> things(N);
>
> In python, I can use a list comprehension.
>
> things = [Thing() for _ in range(N)]
>
> However, the obvious D version doesn't work.
>
> auto things = new Thing[N];
>
> Because Thing.init is null, this produces an array of null
> references. Of course, I can write a for loop to fill in the
> array after creation, but this feels very un-D-like. Is there a
> straightforward way to create a bunch of class instances?
import std.stdio, std.algorithm;
class Thing {
int i;
this(int i) {
this.i = i;
}
}
void main()
{
auto things = new Thing[10];
fill(things, new Thing(5));
foreach (t; things)
writef("%d ", t.i);
}
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jos van Uden | On Sunday, 10 February 2013 at 09:48:04 UTC, Jos van Uden wrote:
> On 10-2-2013 7:14, Simon wrote:
>> Hi, I'm new to the D programming language. Overall I'm liking
>> things very much, but I'm still getting the hang of a few things.
>>
>> Here's a basic programming pattern: I have a class called Thing,
>> and while I'm coding I decide I need N Thing instances.
>>
>> In C++ that's a matter of
>>
>> std::vector<Thing> things(N);
>>
>> In python, I can use a list comprehension.
>>
>> things = [Thing() for _ in range(N)]
>>
>> However, the obvious D version doesn't work.
>>
>> auto things = new Thing[N];
>>
>> Because Thing.init is null, this produces an array of null
>> references. Of course, I can write a for loop to fill in the
>> array after creation, but this feels very un-D-like. Is there a
>> straightforward way to create a bunch of class instances?
>
> import std.stdio, std.algorithm;
>
> class Thing {
> int i;
> this(int i) {
> this.i = i;
> }
> }
>
> void main()
> {
> auto things = new Thing[10];
> fill(things, new Thing(5));
>
> foreach (t; things)
> writef("%d ", t.i);
> }
HELL NO!!!!
What you did just right there is allocate a *single* thing _instance_ and then place 10 _references_ to that same thing in the array.
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon | On Sunday, 10 February 2013 at 06:14:37 UTC, Simon wrote:
> Hi, I'm new to the D programming language. Overall I'm liking
> things very much, but I'm still getting the hang of a few things.
>
> Here's a basic programming pattern: I have a class called Thing,
> and while I'm coding I decide I need N Thing instances.
>
> In C++ that's a matter of
>
> std::vector<Thing> things(N);
>
> In python, I can use a list comprehension.
>
> things = [Thing() for _ in range(N)]
>
> However, the obvious D version doesn't work.
>
> auto things = new Thing[N];
>
> Because Thing.init is null, this produces an array of null
> references. Of course, I can write a for loop to fill in the
> array after creation, but this feels very un-D-like. Is there a
> straightforward way to create a bunch of class instances?
The difference is that C++ will *place* the instances inside the vector. A *true* C++ equivalent would be to declare:
std::vector<Thing*> things(N);
As you can see, same problem.
Honestly, there are a lot of fancy ways to go around the problem, but quite frankly,I think simple is best:
//----
auto myThings = new Thing[](N);
foreach(ref aThing; myThings)
aThing = new Thing();
//-----
It's not fancy, but it gets the job done. You won't confuse anyone with the code, and there is very little risk of subtle bugs (appart from forgetting the ref in the foreach loop.
|
February 10, 2013 Re: Creating an array of default-constructed class instances | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 02/10/2013 03:18 AM, monarch_dodra wrote: > On Sunday, 10 February 2013 at 09:48:04 UTC, Jos van Uden wrote: >> auto things = new Thing[10]; >> fill(things, new Thing(5)); > What you did just right there is allocate a *single* thing _instance_ > and then place 10 _references_ to that same thing in the array. And in case that is what we really wanted, there is the simpler but sometimes confusing array-wise syntax: auto things = new Thing[10]; things[] = new Thing(5); Ali |
Copyright © 1999-2021 by the D Language Foundation