Example of the perils of binding rvalues to const ref

IgorStepanov via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 17 12:28:56 PDT 2014


On Wednesday, 17 September 2014 at 15:03:12 UTC, Andrei 
Alexandrescu wrote:
> On 9/17/14, 3:03 AM, IgorStepanov wrote:
>> BTW. About r-values:
>>
>> void fun(S s)
>> {
>>     fun2(s); //pass s by value.
>> }
>>
>> Now, compiler inserts postblit call before func2 call and dtor 
>> before
>> end of fun.
>
> Is the call to dtor part of fun(), or part of fun()'s call 
> sequence? I've always meant to look at that. LMK if you know 
> for sure.

Dtor call is a part of fun().
I've written test code...
struct Foo
{
     this(int i)
     {
     }

     this(this)
     {
     }

     ~this()
     {
     }
}


void calledFunc(Foo probe)
{
}
void main()
{
     calledFunc(Foo(42));
}

... add a trace output into Statement_toIR::visit(ExpStatement 
*s) ...

printf("ExpStatement::toIR(), exp = %s in %s\n", s->exp ? 
s->exp->toChars() : "", irs->symbol ? irs->symbol->toChars() : 
"NULL");


... and got:
ExpStatement::toIR(), exp = probe.~this() in calledFunc

>> However, it is able to doesn't it, because after fun2 call,
>> s isn't used.
>> Thus, we can implement last postblit optimization:
>> If compiler want to insert postblit, and object is't used 
>> after this
>> postblit, compiler is able to doesn't generate postblit and 
>> last dtor
>> calls.
>> Is there limitation of this optimization?
>> It may 90 percent to solve a r-value ref task.
>
> I think rvalues are already not postblitted into functions. 
> Indeed more postblits can be optimized away for variables are 
> are last used in a function call.
>
>
> Andrei

Yes, rvalues aren't posblitted. However I want and I can't 
deliver without postblits rvalue from first call (of constructor 
or factory function) through intermediate calls to the final 
place of stay.

struct AA(Key, Value)
{
    this(T...)(T args)
    {
       buckets.length = T.length;
       foreach (i; Step2Tuple!(T.length))
       {
             alias key = args[i];
             alias value = args[i+1];
             size_t key_hash = hashOf(key);
             size_t idx = key_hash % T.length;
             auto e = new Entry(key_hash, key, value, 
impl.buckets[idx]);
             buckets[idx] = e;
       }
    }

    ...

     private static struct Entry
     {
         size_t hash;
         Key key;
         Value value;
         Entry* next;
     }

     Entry*[] buckets;
}

AA!(Key, Value) aaLiteral(Key, Value, T...)(auto ref T args)
{
     return AA!(Key, Value)(args);
}


....

//somewhere in user code:

auto aa = aaLiteral!(Foo, int)(Foo(1), 1, Foo(2), 2); //postblits 
aren't called.

I want to place Foo(1) to buckets[nn].key without postblit call. 
Compiler can't help me now, however, I think, It can do it 
without language change.





More information about the Digitalmars-d mailing list