Thread overview
[phobos] What does this code do?
Aug 17, 2010
David Simcha
Aug 18, 2010
David Simcha
August 16, 2010
I'm trying to revamp array() to follow Bearophile's very good suggestion of letting any foreachable object be convertible to an array even if it's opApply-based, not a range.  My efforts have been blocked by this cryptic piece of code:

         foreach (ref e; result)
         {
             // hacky
             static if (is(typeof(&e.opAssign)))
             {
                 // this should be in-place construction
                 new(&e) E(r.front);
             }
             else
             {
                 e = r.front;
             }
             r.popFront;
         }

It took me awhile to even wrap my head around what the point of that code is.  First of all, why are we bypassing opAssign?  Secondly, what if the E doesn't have a constructor that takes only another E as an argument?
August 17, 2010
The idea is to create a typed object in uninitialized memory. Generally using the assignment operator for that is suicide because that guy assumes the object was previously initialized.

Instead of placement new, a better way is to use emplace(). Grep for it to see documentation and examples. Please let us know if you hit another hitch.


Andrei

On 08/16/2010 07:01 PM, David Simcha wrote:
> I'm trying to revamp array() to follow Bearophile's very good suggestion of letting any foreachable object be convertible to an array even if it's opApply-based, not a range. My efforts have been blocked by this cryptic piece of code:
>
> foreach (ref e; result)
> {
> // hacky
> static if (is(typeof(&e.opAssign)))
> {
> // this should be in-place construction
> new(&e) E(r.front);
> }
> else
> {
> e = r.front;
> }
> r.popFront;
> }
>
> It took me awhile to even wrap my head around what the point of that
> code is. First of all, why are we bypassing opAssign? Secondly, what if
> the E doesn't have a constructor that takes only another E as an argument?
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos
August 17, 2010
Sorry for the double mail, Andrei.  I meant to send this to the whole list but my mail client screwed up.

I ran into a few issues w/ emplace while trying to improve array() that I don't know how to fix:

1.  Bug 4671  (http://d.puremagic.com/issues/show_bug.cgi?id=4671). Basically, emplace() doesn't work if args is arguments for a struct literal, not a struct c'tor.  I assume that this is supposed to work. I'm not sure how to fix it because:

a.  Something like the following won't work if the struct contains const/immutable elements that are supposed to be initialized in the c'tor:

foreach(ti, arg; args) {
     (*result).tupleof[ti] = arg;
}

b.  Creating a new struct using args and then using memcpy to copy it to the buffer will do weird things if the struct has a destructor.

c.  Creating a new struct using args, initializing the buffer and then assigning it to *result using opAssign might do weird things if the semantics of opAssign and the semantics of the c'tor aren't the consistent, though this is poor enough design that anyone who does it probably deserves what they get.

2.  I don't understand this code:

     else static if (Args.length == 1)
     {
         // T doesn't define a constructor, must be a primitive type
         static if (is(typeof(result.opAssign(args))))
         {
             static init = T.init;
             memcpy(p, &init, T.sizeof);
         }
         *result = args[0];
     }

How can something be a primitive if it has an opAssign?

3.  In the memcpy() line in the code above, I assume you meant memcpy(result, &init, T.sizeof)?  There is no variable p in that scope.



On 8/17/2010 2:07 PM, Andrei Alexandrescu wrote:
> The idea is to create a typed object in uninitialized memory. Generally using the assignment operator for that is suicide because that guy assumes the object was previously initialized.
>
> Instead of placement new, a better way is to use emplace(). Grep for it to see documentation and examples. Please let us know if you hit another hitch.
>
>
> Andrei
>
> On 08/16/2010 07:01 PM, David Simcha wrote:
>> I'm trying to revamp array() to follow Bearophile's very good suggestion of letting any foreachable object be convertible to an array even if it's opApply-based, not a range. My efforts have been blocked by this cryptic piece of code:
>>
>> foreach (ref e; result)
>> {
>> // hacky
>> static if (is(typeof(&e.opAssign)))
>> {
>> // this should be in-place construction
>> new(&e) E(r.front);
>> }
>> else
>> {
>> e = r.front;
>> }
>> r.popFront;
>> }
>>
>> It took me awhile to even wrap my head around what the point of that
>> code is. First of all, why are we bypassing opAssign? Secondly, what if
>> the E doesn't have a constructor that takes only another E as an
>> argument?
>> _______________________________________________
>> phobos mailing list
>> phobos at puremagic.com
>> http://lists.puremagic.com/mailman/listinfo/phobos
>

August 17, 2010
Submitted a fix, please let me know which of the questions still stand.

Andrei

On 08/17/2010 08:31 PM, David Simcha wrote:
> Sorry for the double mail, Andrei.  I meant to send this to the whole list but my mail client screwed up.
>
> I ran into a few issues w/ emplace while trying to improve array() that
> I don't know how to fix:
>
> 1. Bug 4671 (http://d.puremagic.com/issues/show_bug.cgi?id=4671). Basically, emplace() doesn't work if args is arguments for a struct literal, not a struct c'tor. I assume that this is supposed to work. I'm not sure how to fix it because:
>
> a. Something like the following won't work if the struct contains const/immutable elements that are supposed to be initialized in the c'tor:
>
> foreach(ti, arg; args) {
> (*result).tupleof[ti] = arg;
> }
>
> b. Creating a new struct using args and then using memcpy to copy it to the buffer will do weird things if the struct has a destructor.
>
> c. Creating a new struct using args, initializing the buffer and then assigning it to *result using opAssign might do weird things if the semantics of opAssign and the semantics of the c'tor aren't the consistent, though this is poor enough design that anyone who does it probably deserves what they get.
>
> 2. I don't understand this code:
>
> else static if (Args.length == 1)
> {
> // T doesn't define a constructor, must be a primitive type
> static if (is(typeof(result.opAssign(args))))
> {
> static init = T.init;
> memcpy(p, &init, T.sizeof);
> }
> *result = args[0];
> }
>
> How can something be a primitive if it has an opAssign?
>
> 3. In the memcpy() line in the code above, I assume you meant
> memcpy(result, &init, T.sizeof)? There is no variable p in that scope.
>
>
>
> On 8/17/2010 2:07 PM, Andrei Alexandrescu wrote:
>> The idea is to create a typed object in uninitialized memory. Generally using the assignment operator for that is suicide because that guy assumes the object was previously initialized.
>>
>> Instead of placement new, a better way is to use emplace(). Grep for it to see documentation and examples. Please let us know if you hit another hitch.
>>
>>
>> Andrei
>>
>> On 08/16/2010 07:01 PM, David Simcha wrote:
>>> I'm trying to revamp array() to follow Bearophile's very good suggestion of letting any foreachable object be convertible to an array even if it's opApply-based, not a range. My efforts have been blocked by this cryptic piece of code:
>>>
>>> foreach (ref e; result)
>>> {
>>> // hacky
>>> static if (is(typeof(&e.opAssign)))
>>> {
>>> // this should be in-place construction
>>> new(&e) E(r.front);
>>> }
>>> else
>>> {
>>> e = r.front;
>>> }
>>> r.popFront;
>>> }
>>>
>>> It took me awhile to even wrap my head around what the point of that
>>> code is. First of all, why are we bypassing opAssign? Secondly, what if
>>> the E doesn't have a constructor that takes only another E as an
>>> argument?
>>> _______________________________________________
>>> phobos mailing list
>>> phobos at puremagic.com
>>> http://lists.puremagic.com/mailman/listinfo/phobos
>>
>
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos