Hi all,
I am doing a small exercise before I start implementing the rule of three (five in my case) in a larger code. However the class I am interested in has constant member variables. The reason why I declared them as const is simply that for a given object they will never change during the object's lifetime, yet the values they will hold are not known at compile-time. However, the member variables' const specifier prevents me from implementing "properly" the move-assignement operator (at least, as far as I know…). For similar reasons I can't use the copy-swap idiom for the copy constructor…
Code:
#include <memory>
#include <string>
class ArrayWrapper
{
private:
const std::strin _lbl; //Label for array
std::unique_ptr<double> _arr; //Wrapped array
public:
//DUMMY CONSTRUCTOR
ArrayWrapper(void)
{
//Do nothing
}
// "REGULAR" CONSTRUCTOR
ArrayWrapper
(const std::string lbl //in :Array label
)
:_lbl (lbl )
{
_arr.reset( new double[10] );
}
// DESTRUCTOR
//No need for explicit destructor (?)
// COPY CONSTRUCTOR
ArrayWrapper
(const ArrayWrapper & other //in :Array to copy
)
:_lbl (other._lbl )
{
std::copy(
other._arr.get() ,
other._arr.get() + 10 ,
_arr.get() );
}
// MOVE CONSTRUCTOR
ArrayWrapper
(ArrayWrapper&& other
)
:_lbl ( std::move(other._lbl) ) //No compiler error but will const-declared _lbl actually be moved ?!
,_arr ( std::move(other._arr) )
{
//Do nothing
}
// COPY-ASSIGNMENT OPERATOR
ArrayWrapper &
operator=
(ArrayWrapper other //in :Array to assign
)
{
std::swap( _lbl , other._lbl ); //Compiler error because _lbl is declared as const
return *this;
}
// MOVE-ASSIGNMENT OPERATOR
ArrayWrapper &
operator=
(ArrayWrapper&& other
)
{
std::swap( _lbl , other._lbl ); //Compiler error because _lbl is declared as const
return *this;
}
};
I can emulate the behaviour of such functions by copying the data. However that defeats the purpose of the move-assignment operator…
Code:
//Copy-assignment operator
ArrayWrapper
operator=
(const ArrayWrapper & other //in :Array to assign
)
{
ArrayWrapper Arr(other._lbl);
std::copy(
other._arr.get() ,
other._arr.get() + 10 ,
_arr.get() );
return Arr;
}
//Move assignment operator
ArrayWrapper
operator=
(ArrayWrapper && other
)
{
ArrayWrapper Arr(other._lbl);
std::copy(
other._arr.get() ,
other._arr.get() + 10 ,
_arr.get() );
return Arr;
}
To add to my confusion, here is someone who is claiming that const member variables should only be used in "const classes" (not quite sure what is meant by "const class"). He/She also say that if a class is const then it is fine to not implement the assignment operators (which appears to me as going against the rule of five…).
On a side note, could someone confirm (or refute) that since I don't have any pointers (but merely a smart pointer) I don't need to explicitly declare/implement the destructor. However, doing that would go against the rule of three (five)…
So here is a shorter list of all my questions so far :
- How should I implement the move assignment operator on a class with const member variables ?
- Is it ok to call std::move() in the move constructor in order to initialise a const member variable by swapping its value with another const member variable ? (Compiler does not complain although I was expecting it to)
- Do I need to implement a destructor whenever I have a class containing exclusively member variables that are automatically destructed ?
Looking forward for your answers !