Search code examples
c++c++11move-semanticsrvalue-reference

Re-using code for lvalues and rvalues


Suppose I have a copy constructor. This constructor calls a hierarchy of functions, passing the copied object as an lvalue reference.

Now, I also have a move constructor which basically could use the same function hierarchy as the copy constructor. This would work, since I can pass the rvalue argument to the lvalue hierarchy.

BUT somewhere down in the hierarchy, I have a function which would copy a resource in the lvalue case and 'steal' the resource in the rvalue case.

Is there a way to decide, whether the lvalue reference passed to that function originates from an rvalue? I guess not. Or what is the common approach, when you have a hierarchy of functions for copying which you could use for copy and move constructions and which only differ in very few functions?

Code sample:

class A{
    A(const A& a){
        initFrom(a);  
    }

    A(A&& a){
        initFrom(a); 
    }

    void initFrom(const A& a){
       // call a hierarchy of functions, of which one of them calls initResource(const A&)
    }

    void initResource(const A& a){

       if(a == rvalue reference){ // **** Here's the question... ****
           // steal resource
           this->ptr = a.ptr;
           a.ptr = nullptr;
       }
       else{
           // copy resource
           this->ptr = allocate...
           copy from a.ptr to this->ptr
       }

    }  

Solution

  • This is a typical example for perfect forwarding:

    template <typename T>
    A(T && t) { initFrom(std::forward<T>(a)); }
    
    template <typename T>
    void initFrom(T && t)
    {
        // other calls
        initResource(std::forward<T>(t));
    }
    
    void initResource(A const & rhs) { /* copy from rhs */ }
    void initResource(A && rhs)      { /* move from rhs */ }
    

    (It seems that you should either be able to merge initFrom into the constructor, or otherwise your class may be trying to do too much and you should refactor it into single-responsibility components.)