[dmd-beta] rvalue references

kenji hara k.hara.pg at gmail.com
Fri Apr 13 11:39:05 PDT 2012


How about my idea, Andrei?

Kenji Hara
 2012/04/13 17:47 "kenji hara" <k.hara.pg at gmail.com>:

> I think the main purpose of rvalue reference is:
> "Called function requires the address of given value, but not need to
> change its value semantics."
>
> We can never rewrite basic literals, therefore we can say that they
> have constant value semantics, even if their types are mutable. And
> then, it seems that rewriting literal through rvalue reference (==
> temporary variable) is counter-intuitive, and less useful.
> On the other hand, compound literals usually have mutable
> elements/fields, so called function may use and rewrite them. It is
> often useful.
>
> More details of my proposal with an actual code:
>
> struct S{}
>
> void foo(const ref int v){}
> void foo(const ref double v){}
> void foo(const ref cdouble v){}
> void foo(const ref int[] v){}
> void foo(const ref int[int] v){}
> void foo(const ref S v){}
> void bar(      ref int v){}
> void bar(      ref double v){}
> void bar(      ref cdouble v){}
> void bar(      ref int[] v){}
> void bar(      ref int[int] v){}
> void bar(      ref S v){}
>
> void hoo(T)(const ref T v){}
> void var(T)(      ref T v){}
>
> void main()
> {
>    // cannot bind basic literals to mutable ref
>    enum int ei = 1024;
>    foo(1024);  static assert(!__traits(compiles, bar(1024)));
>    hoo(1024);  static assert(!__traits(compiles, var(1024)));
>    foo(ei);    static assert(!__traits(compiles, bar(ei)));
>    hoo(ei);    static assert(!__traits(compiles, var(ei)));
>
>    enum double ef = 3.14;
>    foo(3.14);  static assert(!__traits(compiles, bar(3.14)));
>    hoo(3.14);  static assert(!__traits(compiles, var(3.14)));
>    foo(ef);    static assert(!__traits(compiles, bar(ef)));
>    hoo(ef);    static assert(!__traits(compiles, var(ef)));
>
>    enum cdouble ec = 1+1i;
>  /*foo(1+1i);*/static assert(!__traits(compiles, bar(1+1i)));
>  /*hoo(1+1i);*/static assert(!__traits(compiles, var(1+1i)));
>    foo(ec);    static assert(!__traits(compiles, bar(ec)));
>    hoo(ec);    static assert(!__traits(compiles, var(ec)));
>
>    // can bind compound literals to mutable ref
>    enum int[] ea = [1,2];
>    foo([1,2]); bar([1,2]);
>    hoo([1,2]); var([1,2]);
>    foo(ea);    bar(ea);
>    hoo(ea);    var(ea);
>
>    enum int[int] eaa = [1:1];
>    foo([1:1]); bar([1:1]);
>    hoo([1:1]); var([1:1]);
>    foo(eaa);   bar(eaa);
>    hoo(eaa);   var(eaa);
>
>    enum S es = S();
>    foo(S());   bar(S());
>    hoo(S());   var(S());
>    foo(es);    bar(es);
>    hoo(es);    var(es);
> }
>
> Kenji Hara
>
> 2012年4月13日14:58 kenji hara <k.hara.pg at gmail.com>:
> > I think to avoid some useless case, I'd like to add a rule.
> >
> > In basic, literals (e.g. 10, 3.14, "hello") in D are typed as mutable.
> > typeof(10) == int
> > typeof(3.14) == double
> > typeof("hello") == immutable(char)[]   // array itself is mutable
> >
> > Then, with new rvalue reference mechanism, literals are assigned to
> > mutable temporaries, and be bound to ref.
> >
> > void foo(ref int n){}
> > foo(10);
> > // same as int tmp = 10; foo(tmp);
> >
> > But it is less useful behavior.
> >
> > I propose that if rvalue reference binding is needed, and the rvalue
> > is built-in literal, its type is treated as const.
> >
> > void foo(ref int n){}
> > foo(10);
> > // same as const(int) tmp = 10; foo(tmp);
> > // tmp is const, and binding const variable to mutable ref is illegal,
> > then raises an error.
> >
> > Finally, I don't know we should apply this rule to struct literal too.
> > It sounds good, but I afraid that is too restrict.
> >
> > Kenji Hara
> >
> > 2012年4月11日13:33 Andrei Alexandrescu <andrei at erdani.com>:
> >> On 4/10/12 7:57 PM, Walter Bright wrote:
> >>>
> >>> 2.
> >>> double& d;
> >>> int i;
> >>> void foo() {
> >>> d = i;
> >>> }
> >>
> >>
> >> This example is off; a reference can't be rebound. The relevant example
> is:
> >>
> >> void increment(double& d)
> >> {
> >>    ++d;
> >> }
> >> ...
> >> int i;
> >> increment(i);
> >>
> >> People think the int has been incremented, but in fact a useless
> temporary
> >> has.
> >>
> >> The discussion about what to do in D has been a bit longer and more
> >> far-reaching than Walter mentioned.
> >>
> >> The long-term plan is to never let the address of a ref escape the
> >> expression in which the ref occurs. That means in essence that user code
> >> can't take the address of a ref.
> >>
> >> Once that is in place, we will know for sure that all ref passed into
> and
> >> returned by functions will not escape the immediate expression in which
> that
> >> happens - great for safe code.
> >>
> >> People who need to take &this and escape it (e.g in linked lists
> implemented
> >> with struct) will not be able to; they'll have to use static functions
> and
> >> pointers for that. Generally any work that involves escaping pointers
> will
> >> have to use pointers, not references.
> >>
> >> I think this puts us in a very good spot:
> >>
> >> 1. Safe code will be able to use ref liberally
> >>
> >> 2. Functions will be able to return ref knowing the ref won't survive
> the
> >> current expression. This is awesome for sealed containers - safe and
> fast.
> >>
> >> What does this have to do with rvalues and lvalues? It means that with
> the
> >> appropriate precautions, we _can_ transform rvalues into lvalues,
> because we
> >> know their address can't unsafely escape.
> >>
> >> There is one precautions to take: we should never convert a value of
> type T
> >> to a ref of another type U. That would cause the problems we learned
> from
> >> C++. There are 3 cases of such implicit conversions:
> >>
> >> 1. built-in numerics, e.g. an int should not convert to a ref double.
> >>
> >> 2. Class inheritance, e.g. a Widget should not convert to a ref Object.
> >>
> >> 3. alias this, e.g.:
> >>
> >> struct T {}
> >> struct A { @property T fun(); alias fun this; }
> >> void fun(ref T);
> >> ...
> >> A a;
> >> fun(a); // should not work
> >>
> >>
> >> I think this all holds water. Destroy!
> >>
> >> Andrei
> >>
> >>
> >> _______________________________________________
> >> dmd-beta mailing list
> >> dmd-beta at puremagic.com
> >> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/dmd-beta/attachments/20120414/5674c4fb/attachment-0001.html>


More information about the dmd-beta mailing list