Search code examples
c++defaultmove-constructormove-assignment-operator

Move constructor and move assignment operator throw error when set to default in .cc source file


I have a template base class that looks roughly like this

Vector.cc:

template<typename T, unsigned int D>
class Vector {

    private:
        T _data[D];

        ...

    public:
        Vector(Vector<T, D>&&);

        ...

    public:
        Vector<T, D>& operator=(Vector<T, D>&&);;
};

extern template class Vector<int, 2>;
extern template class Vector<int, 3>;
extern template class Vector<int, 4>;

Vector.h

// include guard

#include "Vector.h"

template<typename T, unsigned int D>
Vector<T, D>::Vector(Vector<T, D>&&) = default;

template<typename T, unsigned int D>
Vector<T, D>& Vector<T, D>::operator=(Vector<T, D>&&) = default;

template class Vector<int, 2>;
template class Vector<int, 3>;
template class Vector<int, 4>;

// include guard

When i compile this i get the errors error: array used as initializer and error: invalid array assignment and a warning note: synthesized method [...] first required here.

When I put the = default; into the declaration in the .h file i get no errors or warnings.

I've read in multiple sources that i can put the = default; into the definition but for me it doesn't work.

What am I doing wrong? Am I missing something? Or did I simply rely on the wrong sources?


Solution

  • The issue is that the default move is not valid. Inside the class, presumably the compiler doesn't bother generating the code for it, since its likely not used. Putting it outside the class might cause the compiler to decide to compile the operator/constructor.

    Think of it in a basic example:

    int array[5]; 
    int array2[5]; 
    array = array2;
    

    The above is not valid in C++, since arrays cannot be assigned to each other.

    You would have to create your own move operator/constructor for your class in this case.