I'm busy right now, give me some time to look over it.

Thanks,

Andrei

On 4/13/12 1:39 PM, kenji hara wrote:
How about my idea, Andrei?

Kenji Hara

2012/04/13 17:47 "kenji hara" <[email protected]
<mailto:[email protected]>>:

    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 <[email protected]
    <mailto:[email protected]>>:
     > 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 <[email protected]
    <mailto:[email protected]>>:
     >> 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
     >> [email protected] <mailto:[email protected]>
     >> http://lists.puremagic.com/mailman/listinfo/dmd-beta



_______________________________________________
dmd-beta mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/dmd-beta
_______________________________________________
dmd-beta mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/dmd-beta

Reply via email to