this by rvalue

Discussion in 'C++' started by Jan Bielawski, Jun 2, 2009.

  1. I was reading up on the new C++0x features and have a question:

    Is there a way to overload on the rvalue-ness of the invoking object
    itself? In other words, distinguish between:

    // contrived example
    X x;
    x.foo();

    and:

    X f();
    f().foo();

    A less contrived example would be a member X::eek:perator+() which would
    distinguish between the first and the second invocation in the line
    below:

    X x, y, z;
    X xx = x + y + z

    So the first + sign would resolve to <lvalue>.operator+(y), and the
    second + sign would resolve to <rvalue>.operator+(z)
    (where the second one is presumably moving instead of copying).

    Is this available? Is it at all useful? It's as if there was a "&&"
    qualifier (or whatever it's called) analogous to "const" in method
    declaration:

    X X::eek:perator+(const X& rhs) {...} // as usual
    X X::eek:perator+(const X& rhs) && {...} // the one invoked on
    rvalue
    X X::eek:perator+(const X& rhs) const {...} // the one invoked on
    const

    Does this even make any sense?

    --
    Jan
     
    Jan Bielawski, Jun 2, 2009
    #1
    1. Advertising

  2. Jan  Bielawski

    SG Guest

    On 2 Jun., 01:16, Jan Bielawski <> wrote:
    > I was reading up on the new C++0x features and have a question:
    >
    > Is there a way to overload on the rvalue-ness of the invoking object
    > itself? In other words, distinguish between:
    >
    >     // contrived example
    >     X x;
    >     x.foo();
    >
    > and:
    >
    >     X f();
    >     f().foo();


    Yes. That's where "ref qualifiers" come in:

    class X {
    public:
    void foo() &;
    void foo() &&;
    };

    > A less contrived example would be a member X::eek:perator+() which would
    > distinguish between the first and the second invocation in the line
    > below:
    >
    >     X x, y, z;
    >     X xx = x + y + z
    >
    > So the first + sign would resolve to <lvalue>.operator+(y), and the
    > second + sign would resolve to <rvalue>.operator+(z)
    > (where the second one is presumably moving instead of copying).


    Possible but unusable. I would write a free operator+ in terms of +=:

    class X {
    public:
    ...
    X& operator=(X const&) &;
    X& operator=(X &&) &;

    X& operator+=(X const&) &;
    X& operator+=(X &&) &;
    ...
    };

    inline X operator+(X const& lhs, X const& rhs) {
    X temp = lhs;
    temp += rhs;
    return temp;
    }

    inline X operator+(X && lhs, X const& rhs) {
    return std::move(lhs += rhs);
    }

    > Is this available? Is it at all useful? It's as if there was a "&&"
    > qualifier (or whatever it's called) analogous to "const" in method
    > declaration:
    >
    >     X X::eek:perator+(const X& rhs) {...}  // as usual
    >     X X::eek:perator+(const X& rhs) && {...}  // invoked on rvalue
    >     X X::eek:perator+(const X& rhs) const {...}  // invoked on const


    Almost. You can't overload the functions like this. You can't have two
    member function which only differ in one lacking a ref qualifier and
    the other one having some ref qualifier. To make this work you need to
    add an lvalue ref qualifier ("&") for the first function. But what
    would be the difference between the first and the third function? I
    hope none. You should at least remove the first function.

    Cheers!
    SG
     
    SG, Jun 2, 2009
    #2
    1. Advertising

  3. Jan Bielawski wrote:
    >> Is there a way to overload on the rvalue-ness of the invoking object
    >> itself?


    SG wrote:
    > Yes. That's where "ref qualifiers" come in:
    >
    > class X {
    > public:
    > void foo() &;
    > void foo() &&;
    > };


    >> Is this available?


    Good question. Is there any compiler already supporting ref qualifiers for
    member functions?

    >> Is it at all useful?


    I do think so, yes. Have a look at the examples from a paper by Daveed
    Vandevoorde and Bronek Kozicki, Extending Move Semantics To *this,
    www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm

    The first example shows how an lvalue ref qualifier can be used to avoid
    accidentally taking the address of an rvalue, or assigning to an rvalue:

    struct S {
    S* operator &() &;
    S& operator=(S const&) &;
    };

    The second example shows how an rvalue ref qualifier allows move semantics
    for the data of an rvalue object:

    class X {
    std::vector<char> data_;
    public:
    // ...
    std::vector<char> const & data() const & { return data_; }
    std::vector<char> && data() && { return data_; }
    };

    (Both examples are from the paper.)

    Actually I did a proposal to add lvalue ref qualifiers to assignment
    operators in the Standard Library. Written together with Daniel Kruegler:
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2819.html
    Hopefully, it will be discussed during the next meeting of the std
    committee...


    Kind regards, Niels
    --
    Niels Dekker
    http://www.xs4all.nl/~nd/dekkerware
    Scientific programmer at LKEB, Leiden University Medical Center
     
    Niels Dekker - no reply address, Jun 2, 2009
    #3
  4. Jan  Bielawski

    SG Guest

    On 2 Jun., 09:42, "Niels Dekker - no reply address"
    <> wrote:
    >
    > The second example shows how an rvalue ref qualifier allows move semantics
    > for the data of an rvalue object:
    >
    >   class X {
    >    std::vector<char> data_;
    >   public:
    >    // ...
    >    std::vector<char> const & data() const & { return data_; }
    >    std::vector<char> && data() && { return data_; }
    >   };


    Interesting. But this is not in line anymore with the current state of
    rvalues references. It won't compile without an explicit move:

    std::vector<char> && data() && { return std::move(data_); }

    You may even want to return the vector by value to avoid a dangling
    reference in this case:

    X foo();
    std::vector<char> const& bar = foo().data();

    Then again, defining references to const in this way could be a thing
    of the past. I hope people will rely more on copy elision and move
    semantics in these cases. :)

    Cheers!
    SG
     
    SG, Jun 2, 2009
    #4
  5. >> class X {
    >> std::vector<char> data_;
    >> public:
    >> // ...
    >> std::vector<char> const & data() const & { return data_; }
    >> std::vector<char> && data() && { return data_; }
    >> };



    SG wrote:
    > Interesting. But this is not in line anymore with the current state of
    > rvalues references. It won't compile without an explicit move:
    >
    > std::vector<char> && data() && { return std::move(data_); }


    Oops! Sorry for spreading outdated information :-0 The paper is from
    2005.


    > You may even want to return the vector by value to avoid a dangling
    > reference in this case:
    >
    > X foo();
    > std::vector<char> const& bar = foo().data();
    >
    > Then again, defining references to const in this way could be a thing
    > of the past. I hope people will rely more on copy elision and move
    > semantics in these cases. :)


    LOL I'll try to ammend my programming style...

    But in general you may not want to require that your data is
    CopyConstructible (or even MoveConstructible). So you may still want to
    have the rvalue-ref-qualified overload of the data() function return an
    rvalue reference. Don't you think?


    Kind regards, Niels
     
    Niels Dekker - no reply address, Jun 2, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Mantoulidis

    ++x returns lvalue but x++ return rvalue

    Chris Mantoulidis, Dec 28, 2003, in forum: C++
    Replies:
    4
    Views:
    498
    Chris Mantoulidis
    Dec 29, 2003
  2. Gonzalo Aguirre

    rvalue / lvalue operator[]

    Gonzalo Aguirre, Jan 2, 2004, in forum: C++
    Replies:
    4
    Views:
    448
    Ron Natalie
    Jan 2, 2004
  3. Denis Remezov

    lvalue rvalue

    Denis Remezov, Jul 16, 2004, in forum: C++
    Replies:
    12
    Views:
    865
  4. Kavya
    Replies:
    9
    Views:
    513
    Dik T. Winter
    Oct 28, 2006
  5. Juha Nieminen
    Replies:
    13
    Views:
    621
    Edek Pienkowski
    Aug 29, 2012
Loading...

Share This Page