Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

second grade move

Tags:

c++

c++11

Let's say we have a class that embed another parametric one, that has to support both copy and move. And let's assume that -in certain circumstance- there is the need to get out the inner value somehow.

A typical approach can be this one:

template<class T>
class wrapper
{
public:
    wrapper() :val() {}
    wrapper(T s) :val(std::move(s)) {}

    wrapper(const wrapper& s) :val(s.val) {}
    wrapper(wrapper&& s) :val(std::move(s.val)) {}
    wrapper& operator=(wrapper s) { val = std::move(s.val); return *this; }

    T value() const { return val; }
private:
    T val;
};

That's not the only way of doing it, and may be there is no need to expliciate copy and move, but let them be.

The point is another: Suppose T -in ceratin instances- is itself a copy/movable class. Of course, wrapper::value() returns a copy of T.

Now suppose the returned T has to go as a parameter into another call, and that the containing wrapper is temporary.

The simpler simulation is

calledfn(wrapper<T>(someT).value());

Again: done in this way is clueless, but more complex cases require this trivial one to work.

In theory we can admit to move away val from its temporary wrapper to give it to the caller, but... what signature should have the value() method so that it is bound when wrapper<T> is temporary but is not bound when it is not temporary, for which value() const should be preferred?

like image 410
Emilio Garavaglia Avatar asked Apr 02 '26 03:04

Emilio Garavaglia


1 Answers

In C++11 you can overload methods on wether or not the this-pointer is a rvalue:

T value() &&; //Will only be called if the object is a mutable rvalue
T value() const &; //Will only be called if the object is an lvalue

Note that according to 13.1.2 [over.load]in the standard if any overload has a reference specifier (lvalue or rvalue) all have to get one. So The overload for the non-temporary case has to be const &. I'm not completely sure wether or not this will bind to a const r-value, so you might need a const && overload to catch that case.

I don't know about the compiler support for this feature, so this might be somewhat theoretical if the support isn't there yet. In that case you might work around by creating a move_value method and using a free function which dispatches to the correct method:

template<class T> class wrapper {
    ...    
    T value() const;
    T move_value();    
};
template<typename T> T value(wrapper<T>&& self) { return std::move(self.move_value(); }
template<typename T> T value(const wrapper<T>& self) { return std::move(self.value(); }
like image 50
Grizzly Avatar answered Apr 03 '26 18:04

Grizzly



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!