2

I have a class containing pointers to objects and a subclass of it. The subclass "move" constructor I want to call the base class move constructor for obvious reasons. With MSVS 2017 compiler this does not seem to work.

template<class SubT>
class MyMovingBase {
    typedef MyMovingBase<MtY> ThisT; 
protected:
    MyMovingBase(const ThisT &src) {
         // update copy and or reference DO NOT Move
    }
    MyMovingBase(ThisT &&src) { 
         // move stuff from src to this, invalidate src
     }
};

class Subclass
    : public MyMovingBase<SubClass>
{
public:
    Subclass(const Subclass &src) : MyMovingBase<SubClass>(src) {
        // does what is expected, calls copy constructor.
    }
    Subclass(Subclass &&src) : MyMovingBase<SubClass>(src) {
        // the above initializer calls copy constructor and NOT
        // the move constructor for MyMovingBase !!!!!!
    }
};

How do I make this do what I want ??

Of course I want it to work in gcc and clang as well.

peterk
  • 5,136
  • 6
  • 33
  • 47
  • 3
    `MyMovingBase(std::move(src))` Note that `src` is an rvalue reference but is itself an lvalue so won't bind to another rvalue reference on it's own. – François Andrieux Jan 16 '19 at 15:48
  • will try it :) seems pretty nasty though.seems like a (Class &&) cast would be more language consistent. – peterk Jan 16 '19 at 15:50
  • 4
    Save yourself and use the rule of zero `class Subclass : public MyMovingBase {}` will automagically call the base class constructors for you since the compiler generated defaults "do the right thing" – NathanOliver Jan 16 '19 at 15:51
  • 1
    Since `MyMovingBase` and `Subclass` are your own class, the guaranties regarding the post-move state is entirely in your hands. I don't see what's nasty about it. – François Andrieux Jan 16 '19 at 15:51
  • What is `MtY` ? – eerorika Jan 16 '19 at 15:51
  • 1
    The nastiness in is the syntax not the flexibility :) – peterk Jan 16 '19 at 15:53
  • Thanks for the duplicate pointer - their smart duplicate finder didn't show this one and I didn't see it :) – peterk Jan 16 '19 at 15:57
  • 1
    @peterk If somebody has flagged up one of your questions as duplicate, you can close it yourself as duplicate. (I found this myself on another site.) – Martin Bonner supports Monica Jan 16 '19 at 16:02
  • Often though having a number of ways of expressing the question in the database inproves seachability however :) I have often found an answer by finding questions flagged as duplicates that led me to the best answer. – peterk Jan 16 '19 at 16:08

1 Answers1

4

In general, marking some variable as rvalue reference with && does not mean that it keeps this status when passing src further. I mean, after all, the variable has a name in the context of the constructor and can therefore obviously be used as lvalue. In fact, the expression src is indeed an lvalue. src is passed to your constructor as rvalue because the caller intended to have it interpreted as such.

Now, in your constructor, the variable is actually named and using this name leads to an expression that needs to be explicitly marked as rvalue reference to be interpreted as such. Otherwise, it just is an lvalue. This is why you have to move it again to be interpreted by the callee (here, MyMovingBase::ctor) as rvalue whose contents are allowed to be moved out of the original object.

Therefore, François' comment is correct. Using

Subclass(Subclass &&src) : MyMovingBase<SubClass>(std::move(src))

does the trick.

IceFire
  • 4,016
  • 2
  • 31
  • 51