2

I would like to implement a "take" method. A "take" method is something like a get method, but which steals the getted object from its owner: the owner is left with that object in an empty state. Of course, this involves the C++11 move semantics. But which of the following is the best way to implement it?

class B
{
public:

    A take_a_1()
    {
        return std::move(m_a);
    }

    // this can be compiled but it looks weird to me that std::move 
    // does not complain that I'm passing a constant object
    A take_a_2() const
    {
        return std::move(m_a);
    }

    A&& take_a_3()
    {
        return std::move(m_a);
    }

    // this can't be compiled (which is perfectly fine)
    //
    // A&& take_a_4() const
    // {
    //     return std::move(m_a);
    // }

private:

    A m_a;
};
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
nyarlathotep108
  • 5,275
  • 2
  • 26
  • 64

1 Answers1

4

None of them. I'd use this:

struct B
{
    A && get() && { return std::move(m_a); }
};

That way you can only "take" from rvalues of B:

B b;
A a = std::move(b).get();
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • This is very interesting. Could you explain why is better taking only from rvalues of the whole B object? – nyarlathotep108 Feb 05 '16 at 17:32
  • 4
    @nyarlathotep108: Well, leaving the object behind in a mutilated state only seems unconditionally desirable if the object itself is no longer observable (i.e. an rvalue). Otherwise you're going to have to specify detailed semantics of how the taking works and how the remaining object behaves. – Kerrek SB Feb 05 '16 at 19:12
  • 1
    @nyarlathotep108 Also, crucially, since `m_a` is part of `B`, and the state of an object is only *guaranteed* to be destructible after it's been moved-from (*nothing* else is guaranteed), `B`'s state after moving-from `m_a` is such that, again, the *only* safe operation is destruction. Functions that invalidate the state of an object should generally only take R-values of that object so that this state-invalidation is apparent from the interface. – Kyle Strand Feb 08 '16 at 19:28