I thought that the topic had been covered but after giving it another look today it seems it's not…
This :
Originally Posted by
whiteflags
Code:
std::swap(this->val_, other.val_);
std::swap(this->MyOwn_, other.MyOwn_);
is not enough to give the right values to "Wrapper::PtrOwner::myPtr_" . As a solution, I added calls to a setter method.
Code:
std::swap( this->val_ , other.val_ );
std::swap( this->MyOwn_, other.MyOwn_ );
this->MyOwn_.setPtr( &(this->val_) );
other.MyOwn_.setPtr( &(other.val_) );
It works but was that the right way to achieve this ?
The full code :
Code:
#include <cassert>
#include <iostream>
#include <vector>
///////////////////////////////////////////////////////////
class PtrOwner
{
public:
//Constructor
PtrOwner(double & var) : myPtr_ (&var) {}
//Default copy/move constructor/assign-op are used
//Getters & setters
double * getPtr(void) { return myPtr_; }
void setPtr(double * newPtr) { myPtr_ = newPtr; }
//Attributes (would be private in an actual code)
std::vector<double> massiveVar; //Member variable that's too "massive" to be copied cheaply
double * myPtr_;
};
///////////////////////////////////////////////////////////
class Wrapper
{
public:
//Constructor
Wrapper(void) : val_ (2.0), MyOwn_ (val_) {}
//Copy constructor
Wrapper(const Wrapper & other)
:val_ (other.val_ )
,MyOwn_(other.MyOwn_)
{
this->MyOwn_.setPtr( &(this->val_) );
}
//Move constructor
Wrapper(/***/ Wrapper && other)
:val_ ( std::move(other.val_ ) )
,MyOwn_( std::move(other.MyOwn_) )
{
this->MyOwn_.setPtr( &(this->val_) );
}
//Copy/move assignment operator
Wrapper & operator= (Wrapper other)
{
other.swap(*this);
return *this;
}
//Swap function
void swap(Wrapper& other)
{
std::swap( this->val_ , other.val_ );
std::swap( this->MyOwn_, other.MyOwn_ );
this->MyOwn_.setPtr( &(this->val_) );
other.MyOwn_.setPtr( &(other.val_) );
}
//Attributes (would be private in an actual code)
double val_;
PtrOwner MyOwn_;
};
///////////////////////////////////////////////////////////
bool
test_objIsConsistent
(const Wrapper & myWrp
)
{
return myWrp.MyOwn_.myPtr_ == &(myWrp.val_);
}
///////////////////////////////////////////////////////////
void dispInfo
(const std::string objNm //Name of object
,Wrapper & Wrp //Object
)
{
std::cout << "\t";
std::cout << objNm + ".val_ = " << static_cast<void*>(&(Wrp.val_)) << " ; ";
std::cout << objNm + ".MyOwn_.myPtr_ = " << static_cast<void*>(Wrp.MyOwn_.myPtr_) << " ; ";
std::cout << std::endl;
}
///////////////////////////////////////////////////////////
int main(void)
{
//CONSTRUCTOR
Wrapper WrpA;
std::cout << "After construction" << std::endl;
dispInfo( "WrpA", WrpA );
std::cout << std::endl;
assert( test_objIsConsistent(WrpA) );
//COPY CONSTRUCTOR
Wrapper WrpB = WrpA;
std::cout << "After copy construction" << std::endl;
dispInfo( "WrpA", WrpA );
dispInfo( "WrpB", WrpB );
std::cout << std::endl;
assert( test_objIsConsistent(WrpA) );
assert( test_objIsConsistent(WrpB) );
//MOVE CONSTRUCTOR
Wrapper WrpC = std::move(WrpA);
std::cout << "After move construction" << std::endl;
dispInfo( "WrpA", WrpA );
dispInfo( "WrpC", WrpC );
std::cout << std::endl;
assert( test_objIsConsistent(WrpA) );
assert( test_objIsConsistent(WrpC) );
//COPY ASSIGNMENT OPERATOR
Wrapper WrpD;
WrpD = WrpA;
std::cout << "After copy assignment" << std::endl;
dispInfo( "WrpA", WrpA );
dispInfo( "WrpD", WrpD );
std::cout << std::endl;
assert( test_objIsConsistent(WrpA) );
assert( test_objIsConsistent(WrpD) );
//MOVE ASSIGNMENT OPERATOR
Wrapper WrpE;
WrpE = std::move(WrpA);
std::cout << "After move assignment" << std::endl;
dispInfo( "WrpA", WrpA );
dispInfo( "WrpE", WrpE );
std::cout << std::endl;
assert( test_objIsConsistent(WrpA) );
assert( test_objIsConsistent(WrpE) );
return 0;
}