I understand if you wish to pass a vector of MyClass objects and it is a temporary variable, if there is a move constructor defined for MyClass then this will be called, but what happens if you pass a vector of boost::shared_ptr<MyClass> or std::shared_ptr<MyClass>? Does the shared_ptr have a move constructor which then call's MyClass's move constructor?
if there is a move constructor defined for MyClass then this will be called
Usually not. Moving a vector is usually done my transferring ownership of the managed array, leaving the moved-from vector empty. The objects themselves aren't touched. (I think there may be an exception if the two vectors have incompatible allocators, but that's beyond anything I've ever needed to deal with, so I'm not sure about the details there).
Does the shared_ptr have a move constructor which then call's MyClass's move constructor?
No. Again, it has a move constructor which transfers ownership of the MyClass object to the new pointer, leaving the old pointer empty. The object itself is untouched.
Yes, std::shared_ptr<T> has a move constructor, as well as a templated constructor that can move from related shared pointers, but it does not touch the managed object at all. The newly constructed shared pointer shares ownership of the managed object (if there was one), and the moved-from pointer is disengaged ("null").
Example:
struct Base {}; // N.B.: No need for a virtual destructor
struct Derived : Base {};
auto p = std::make_shared<Derived>();
std::shared_ptr<Base> q = std::move(p);
assert(!p);
If you mean moving std::vector<std::shared_ptr<MyClass>>. Then even the move constructor of std::shared_ptr won't be called. Because the move operation is directly done on std::vectorlevel.
For example, a std::vector<T> may be implemented as a pointer to array of T, and a size member. The move constructor for this can be implemented as:
template <typename T>
class vector {
public:
/* ... other members */
vector(vector &&another): _p(another._p), _size(another._size) {
/* Transfer data ownership */
another._p = nullptr;
another._size = 0;
}
private:
T *_p;
size_t _size;
}
You can see in this process, no data member of type T is touched at all.
EDIT: More specially in C++11 Standard: ยง23.2.1. General container requirements (4) there is a table contains requirements on implementations of general containers, which contains following requirements:
(X is the type of the elements, u is an identifier declaration, rv is rvalue reference, a is a container of type X)
X u(rv)
X u = rv
C++ Standard: These two (move constructors) should have constant time complexity for all standard containers except std::array.
So it's easy to conclude implementations must use a way like I pointed above for move constructors of std::vector since it cannot invoke move constructors of individual elements or the time complexity will become linear time.
a = rv
C++ Standard: All existing elements of a are either move assigned to or destroyed a shall be equal to the value that rv had before this assignment.
This is for move assign operator. This sentence only states that original elements in a should be "properly handled" (either move-assigned in or destroyed). But this is not a strict requirement. IMHO implementations can choose the best suited way.
I also looked at code in Visual C++ 2013 and this is the snippet I found (vector header, starting from line 836):
/* Directly move, like code above */
void _Assign_rv(_Myt&& _Right, true_type)
{ // move from _Right, stealing its contents
this->_Swap_all((_Myt&)_Right);
this->_Myfirst = _Right._Myfirst;
this->_Mylast = _Right._Mylast;
this->_Myend = _Right._Myend;
_Right._Myfirst = pointer();
_Right._Mylast = pointer();
_Right._Myend = pointer();
}
/* Both move assignment operator and move constructor will call this */
void _Assign_rv(_Myt&& _Right, false_type)
{ // move from _Right, possibly moving its contents
if (get_allocator() == _Right.get_allocator())
_Assign_rv(_STD forward<_Myt>(_Right), true_type());
else
_Construct(_STD make_move_iterator(_Right.begin()),
_STD make_move_iterator(_Right.end()));
}
In this code the operation is clear: if both this and right operand have the same allocator, it will directly steal contents without doing anything on individual elements. But if they haven't, then move operations of individual elements will be called. At this time, other answers apply (for std::shared_ptr stuff).
Related
I am looking at some code that I have inherited and it has a matrix class which implements 2D matrices in C++ and has move constructors and assignment operator.
The way it is implemented is as follows:
template<typename T, int rows, int cols>
class matrix_data {
...
std::unique_ptr<T[]> data_;
// Some definitions
typedef matrix_data<T, rows, cols> this_type
matrix_data(this_type && other)
{
std::swap(data_, other.data_);
}
};
Now, I am not sure why the data pointers are being swapped here. I thought it should be something like
data_ = std::move(other.data_);
I am guessing with the swap it is still ok because the other instance should be in an invalid state anyway after the move.
My question is whether I can replace the statement with data_ = std::move(other.data_); Is there some unique_ptr deletion stuff that is the reason for doing the swap instead of the move i.e. if I do the move would the original data be deleted correctly?
To answer your question:
Yes, you could replace the swapping with
data_ = std::move(other.data_);
but as the comments suggest, that's happening anyway when you do not implement the move constructor, as long as you do not implement neither a copy constructor, copy assignment operator, move assignment operator or destructor. If you have implemented one of the above, marking the move constructor as =default will also do the job.
Swapping the objects' contents is indeed not necessary in this case as there is actually nothing to swap, because this being a (move) constructor, this->data_ does not point to any previously allocated memory location that should be freed after the pointer to it has been overwritten.
Therefore swapping is usually done when implementing the move assignment operator, because in this case this->data_ usually holds a pointer to a memory location that needs to be freed sometime. By putting this pointer into the moved-from object, the memory it is pointing to will be freed when the destructor for the moved-from object is called.
The title pretty much sums up my question. In more detail: I know that when I declare a move constructor and a move assignment operator in C++11 I have to "make the other objects variables zero". But how does that work, when my variable is not an array or a simple int or double value, but its a more "complex" type?
In this example I have a Shoplist class with a vector member variable. Do I have to invoke the destructor of the vector class in the move assignment operator and constructor? Or what?
class Shoplist {
public:
Shoplist() :slist(0) {};
Shoplist(const Shoplist& other) :slist(other.slist) {};
Shoplist(Shoplist&& other) :slist(0) {
slist = other.slist;
other.slist.~vector();
}
Shoplist& operator=(const Shoplist& other);
Shoplist& operator=(Shoplist&& other);
~Shoplist() {};
private:
vector<Item> slist;
};
Shoplist& Shoplist::operator=(const Shoplist& other)
{
slist = other.slist;
return *this;
}
Shoplist& Shoplist::operator=(Shoplist&& other)
{
slist = other.slist;
other.slist.~vector();
return *this;
}
Whatever a std::vector needs to do in order to move correctly, will be handled by its own move constructor.
So, assuming you want to move the member, just use that directly:
Shoplist(Shoplist&& other)
: slist(std::move(other.slist))
{}
and
Shoplist& Shoplist::operator=(Shoplist&& other)
{
slist = std::move(other.slist);
return *this;
}
In this case, you could as AndyG points out, just use = default to have the compiler generate exactly the same move ctor and move assignment operator for you.
Note that explicitly destroying the original as you did is definitely absolutely wrong. The other member will be destroyed again when other goes out of scope.
Edit: I did say assuming you want to move the member, because in some cases you might not.
Generally you want to move data members like this if they're logically part of the class, and much cheaper to move than copy. While std::vector is definitely cheaper to move than to copy, if it holds some transient cache or temporary value that isn't logically part of the object's identity or value, you might reasonably choose to discard it.
Implementing copy/move/destructor operations doesn't make sense unless your class is managing a resource. By managing a resource I mean be directly responsible for it's lifetime: explicit creation and destruction. The rule of 0 and The rule of 3/5 stem from this simple ideea.
You might say that your class is managing the slist, but that would be wrong in this context: the std::vector class is directly (and correctly) managing the resources associated with it. If you let our class have implicit cpy/mv ctos/assignment and dtors, they will correctly invoke the corresponding std::vector operations. So you absolutely don't need to explicitly define them. In your case the rule of 0 applies.
I know that when I declare a move constructor and a move assignment
operator in C++11 I have to "make the other objects variables zero"
Well no, not really. The ideea is that when you move from an object (read: move it's resource from an object) then you have to make sure that your object it's left aware that the resource it had is no more under it's ownership (so that, for instance, it doesn't try to release it in it's destructor). In the case of std::vector, it's move ctor would set the pointer it has to the internal buffer to nullptr.
I know that when I declare a move constructor and a move assignment operator in C++11 I have to "make the other objects variables zero"
This is not quite correct. What you must do, is maintain validity of the moved from object. This means that you must satisfy the class invariant.
If you have specified a special invariant for a particular class, that requires you to set member variables to zero, then perhaps such class might have to do so. But this is not a requirement for move in general.
Do I have to invoke the destructor of the vector class in the move assignment operator and constructor?
Definitely not. The destructors of the members will be called when the moved from object is destroyed.
What you would typically do, is move construct/assign each member in the move constructor/assignment operator of the containing object. This is what the implicitly generated special member functions do. Of course, this might not satisfy the class invariant for all classes, and if it doesn't, then you may need to write your own versions of them.
The compiler will implicitly generate the special member functions for you, if you don't try to declare them yourself. Here is a minimal, but correct version of your class:
class Shoplist {
vector<Item> slist;
};
This class is default constructible, movable and copyable.
The move constructor should move member-wise:
Shoplist(Shoplist&& other)
: slist(std::move(other.slist))
{}
Note, that the compiler generates move constructors for you (when possible) by member-wise move, as you would do by hand above.
Move constructors are allowed (but not required) "steal" the contents of the moved-from object. This does not mean that they must "make the other objects variables zero". Moving a primitive type, for instance, is equivalent to copying it. What it does mean is that a move constructor can transfer ownership of data in the heap or free store. In this case, the moved-from object must be modified so that when it is destroyed (which should not happen in the move-constructor), the data it previously owned (before it was transferred) will not be freed.
Vector provides its own move constructor. So all you need to do in order to write a correct move constructor for an object containing a vector is to ensure the correct vector constructor is invoked. This is done by explicitly passing an r-value reference to the sub-object constructor, using std::move:
Shoplist(Shoplist&& other) :slist(std::move(other.slist)) {
//... Constructor body
... But in fact you probably don't need to do this in general. Your copy and move constructors will be correctly auto-generated if you don't declare them and don't declare a destructor. (Following this practice is called the "rule of 0".)
Alternatively, you can force the compiler to auto-generate the move constructor:
Shoplist(Shoplist&& other) = default;
I am working with writing the big five(copy constructor, copy assignment operator, move constructor, move assignment operator, destructor). And I've hit a bit of a snag with the copy constructor syntax.
Say I have a class foo that has the following private members:
template<class data> // edit
class foo{
private:
int size, cursor; // Size is my array size, and cursor is the index I am currently pointing at
data * dataArray; // edit
}
If I were to write a constructor for this of some arbitrary size X it would look like this.
template<class data> // edit
foo<data>::foo(int X){
size = X;
dataArray = new data[size];
cursor = 0; // points to the first value
}
Now if I wanted to make a copy constructor of another object called bar I'd need to make the following:
template<class data> // edit
foo<data>::foo(foo &bar){
foo = bar; // is this correct?
}
Assuming I have the overloaded = from the code below:
template<class data> // edit
foo<data>::operator=(foo &someObject){
if(this != someObject){
size = someObject.size;
cursor = someObject.cursor;
delete[] dataArray;
dataArray = new data[size];
for(cursor = 0; cursor<size-1;cursor++)
dataArray[cursor] = someObject.dataArray[cursor];
}
else
// does nothing because it is assigned to itself
return *this;
}
Is my copy constructor correct? Or should foo = bar instead be *this = bar ?
I'm still new to templated constructors so if I made any errors in the code please let me know I will correct it.
EDIT 1: Thanks to the answer provided below by Marcin I have made some edits to the code above to make it more syntatically correct and commented them with //edit they are summarized in the list below:
previously template<classname data>, which is incorrect must be template <typename data> or template <class data> for functions and classes respectively.
previously int*dataArray; this missuses the template and should be data* dataArray;
The best way to achieve what you want is to use a class that already handles assignment, copying and moving, taking care of its memory management for you. std::vector does exactly this, and can directly replace your dynamically allocated array and size. Classes that do this are often referred to as RAII classes.
Having said that, and assuming this is an exercise in correctly implementing the various special member functions, I'd suggest that you proceed via the copy and swap idiom. (See What is the copy and swap idiom? on SO, for more details and commentary). The idea is to define the assignment operation in terms of the copy constructor.
Start with the members, constructor and destructor. These define the ownership semantics of the members of your class:
template <class data>
class foo {
public:
foo(const size_t n);
~foo();
private:
size_t size; // array size
size_t cursor; // current index
data* dataArray; // dynamically allocated array
};
template <class data>
foo<data>::foo(const size_t n)
: size(n), cursor(0), dataArray(new data[n])
{}
template <class data>
foo<data>::~foo() {
delete[] dataArray;
}
Here, memory is allocated in the constructor and deallocated in the destructor.
Next, write the copy constructor.
template <class data>
foo<data>::foo(const foo<data>& other)
: size(other.size), cursor(other.cursor), dataArray(new data[other.size]) {
std::copy(other.dataArray, other.dataArray + size, dataArray);
}
(along with the declaration, foo(const foo& other); inside the class body).
Notice how this uses member initialiser lists to set the member variables to the values in the other object. A new allocation is performed, and then in the body of the copy constructor you copy the data from the other object into this object.
Next comes the assignment operator. Your existing implementation has to perform a lot of manipulation of pointers, and isn't exception safe. Let's look at how this could be done more simply and more safely:
template <class data>
foo<data>& foo<data>::operator=(const foo<data>& rhs) {
foo tmp(rhs); // Invoke copy constructor to create temporary foo
// Swap our contents with the contents of the temporary foo:
using std::swap;
swap(size, tmp.size);
swap(cursor, tmp.cursor);
swap(dataArray, tmp.dataArray);
return *this;
}
(along with the declaration in-class, foo& operator=(const foo& rhs);).
[-- Aside: You can avoid writing the first line (explicitly copying the object) by accepting the function argument by value. It's the same thing, and might be more efficient in some cases:
template <class data>
foo<data>& foo<data>::operator=(foo<data> rhs) // Note pass by value!
{
// Swap our contents with the contents of the temporary foo:
using std::swap;
swap(size, rhs.size);
swap(cursor, rhs.cursor);
swap(dataArray, rhs.dataArray);
return *this;
}
However, doing so may cause ambiguous overloads if you also define a move assignment operator. --]
The first thing this does is create a copy of the object being assigned from. This makes use of the copy constructor, so the details of how an object is copied need only be implemented once, in the copy constructor.
Once the copy has been made, we swap our internals with the internals of the copy. At the end of the function body, the tmp copy goes out of scope, and its destructor cleans up the memory. But this isn't the memory that was allocated at the beginning of the function; it's the memory our object used to hold, before we swapped our state with the temporary.
In this way, the details of allocating, copying and deallocating are kept where they belong, in the constructors and the destructor. The assignment operator simply copies and swaps.
This has a further advantage, over and above being simpler: It's exception safe. In the code above, an allocation error could cause an exception to be thrown while creating the temporary. But we haven't modified the state of our class yet, so our state remains consistent (and correct) even when the assignment fails.
Following the same logic, the move operations become trivial. The move constructor must be defined to simply take ownership of the resource and leave the source (the moved-from object) in a well-defined state. That means setting the source's dataArray member to nullptr so that a subsequent delete[] in its destructor doesn't cause problems.
The move assignment operator can be implemented similarly to the copy assignment, although in this case there's less concern with exception safety since you're just stealing the already-allocated memory of the source object. In the complete example code, I opted to simply swap the state.
A complete, compilable-and-runnable example can be seen here.
Your foo class does not internally use data template parameter. I suppose you wanted to use it here:
int * dataArray; // should be: data * dataArray;
You also are not allowed to use classname keyword but typename or class. You have also lots of other compile errors in your code.
Your copy constructor is wrong, it will not compile:
foo = bar; // is this correct? - answer is NO
foo is a class name in this context, so your assumption is correct. *this = someObject this would work (with additional fixes, at least dataArray must be set to nullptr), but your class variables would be default constructed first by copy constructor only to be overwritten by assignment operator, so its quiet non efficent. For more read here:
Calling assignment operator in copy constructor
Is it bad form to call the default assignment operator from the copy constructor?
I have some questions about unrestricted unions and their application in practice.
Let's suppose I have the following code :
struct MyStruct
{
MyStruct(const std::vector<int>& a) : array(a), type(ARRAY)
{}
MyStruct(bool b) : boolean(b), type(BOOL)
{}
MyStruct(const MyStruct& ms) : type(ms.type)
{
if (type == ARRAY)
new (&array) std::vector<int>(ms.array);
else
boolean = ms.boolean;
}
MyStruct& operator=(const MyStruct& ms)
{
if (&ms != this) {
if (type == ARRAY)
array.~vector<int>(); // EDIT(2)
if (ms.type == ARRAY)
new (&array) std::vector<int>(ms.array);
else
boolean = ms.boolean;
type = ms.type;
}
return *this;
}
~MyStruct()
{
if (type == ARRAY)
array.~vector<int>();
}
union {
std::vector<int> array;
bool boolean;
};
enum {ARRAY, BOOL} type;
};
Is this code valid :) ?
Is it necessary to explicitly call the vector destructor each time we are using the boolean (as stated here http://cpp11standard.blogspot.com/2012/11/c11-standard-explained-1-unrestricted.html)
Why a placement new is required instead of just doing something like 'array = ms.array' ?
EDIT:
Yes, it compiles
"Members declared inside anonymous unions are actually members of the containing class, and can be initialized in the containing class's constructor." (C++11 anonymous union with non-trivial members)
Adding explicit destructors as suggested, leads to SIGSEV with g++ 4.8 / clang 4.2
The code's buggy: change array.clear(); to array.~vector<int>();
Explanation: operator= is using placement new over an object that hasn't been destructed, which could do anything but practically you can expect it to leak the dynamic memory the previous array had been using (clear() doesn't release memory / change capacity, it just destructs elements and changes size).
From 9.5/2:
If any non-static data member of a union has a non-trivial default
constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move
assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union.
So, the vector constructor, destructor etc never kicks in by themselves: you must call them explicitly when wanted.
In 9.5/3 there's an example:
Consider the following union:
union U {
int i;
float f;
std::string s;
};
Since std::string (21.3) declares non-trivial versions of all of the special member functions, U will have
an implicitly deleted default constructor, copy/move constructor, copy/move assignment operator, and destructor.
To use U, some or all of these member functions must be user-provided.
That last bit - "To use U, some or all of these member functions must be user-provided." - seems to presume that U needs to coordinate its own vaguely value-semantic behaviour, but in your case the surrouding struct is doing that so you don't need to define any of these union member functions.
2: we must call the array destructor whenever an array value is being replaced by a boolean value. If in operator= a new array value is being placement-newed instead of assigned, then the old array must also have its destructor called, but using operator= would be more efficient when the existing memory is sufficient for all the elements being copied. Basically, you must match constructions and destructions. UPDATE: the example code has a bug as per your comment below.
3: Why a placement new is required instead of just doing something like 'array = ms.array' ?
array = ms.array invokes std::vector<int>::operator= which always assumes the this pointer addresses an already properly constructed object. Inside that object you can expect there to be a pointer which will either be NULL or refer to some internal short-string buffer, or refer to heap. If your object hasn't been destructed, then operator= may well call a memory deallocation function on the bogus pointer. Placement new says "ignore the current content of the memory that this object will occupy, and construct a new object with valid members from scratch.
The union does not declare a default constructor, copy constructor, copy assignment operator, or destructor.
If std::string declares at least one non-trivial version of a special member function (which is the case), the forementioned ones are all implicitly deleted, and you must declare (and define) them (... if they're used, which is the case).
Insofar, that code isn't correct and should not successfully compile (this is almost-to-the-letter identical to the example in 9.5 par 3 of the standard, except there it's std::string, not std::vector).
(Does not apply for an anon union, as correctly pointed out)
About question (2): In order to safely switch the union, this is necessary, yes. The Standard explicitly says that in 9.5 par 4 [Note].
It makes sense too, if you think about it. At most one data member can be active in a union at any time, and they're not magically default constructed/destroyed, which means you need to properly construct/destruct things. It is not meaningful (or even defined) to use the union as something else otherwise (not that you couldn't do that anyway, but it's undefined).
The object is not a pointer, and you don't know whether it's allocated on the heap either (even if it is allocated on the heap, then it's inside another object, so it's still not allowable to delete it). How do you destroy an object if you can't call delete? How do you allocate an object -- possibly several times -- without leaking if you can't delete it? This doesn't leave many choices. Insofar, the [Note] makes perfect sense.
For customized use, I have inherited std::vector to a custom class Vector. For my requirement this public inheritance is ok.
One intention is to avoid making copies of a vector array multiple times, so I decided this custom class to be 'ownership' based.
Vector<A> vA1(100); // vA1 is allocated A[100]
Vector<A> vA2 = vA1; // vA2 refers to original A[100] and ...
// ... vA1 is now blank which is expected
This is how it's implemented for C++03:
template<typename T>
struct Vector : std::vector<T>
{
// ... other constructors
Vector (const Vector ©) // copy constructor
{
this->swap(const_cast<Vector&>(copy)); // <---- line of interest
}
// 'operator =' is TBD (either same as above or unimplemented)
};
Am I breaking any language rule/feature/convention ? Is there anything bad in this code ?
Edit: I have added my new approach in form of answer below (Here is its working demo).
I think what you are looking for are move semantics.
Vector<A> vA1(100); // vA1 is allocated A[100]
Vector<A> vA2 = std::move(vA1); // vA2 refers to original A[100] and ...
// ... vA1 is now blank which is expected
If your compiler doesn't have move semantics support I would suggest you use smart pointers or take a look at boost::move which can emulate move semantics in pre C++11 compilers..
std::shared_ptr<Vector<A>> vA1(new Vector<A>(100)); // vA1 is allocated A[100]
std::shared_ptr<Vector<A>> vA2 = vA1; // vA2 refers to original A[100] and ...
vA1.reset();
// ... vA1 is now blank which is expected
or even simpler:
Vector<A> vA1(100); // vA1 is allocated A[100]
Vector<A> vA2;
vA1.swap(vA2);// vA2 refers to original A[100] and ...
// ... vA1 is now blank which is expected
You should really have a look at using C++11: all the standard containers are movable and are thus resembling your semantics in many cases, namely when it is known that the ownership can be transferred. More precisely, containers get moved rather than copied when returning objects from function or when using a temporary to construct or assign an object. Trying to replicate this mechanism in some way will almost certainly yield unexpected behavior in may cases.
In C++11 the movable semantics are integrated into the language and functions, including constructors and assignments, can be overloaded to behave different depending on whether the object is movable or not.
Your code breaks the conventions that support const-correctness:
const Vector<int> foo(12);
const Vector<int> bar(foo); // UB.
some_function_that_takes_Vector_by_value(bar); // UB.
You might say, "but nobody will ever create a const instance of Vector, so the UB will never happen". In which case, you could at least make your copy ctor take a non-const reference in order to follow the convention that functions shouldn't modify objects taken by const& parameters.
Even then, personally I'd prefer to require the user to "switch on" speed by explicitly swapping, than to create traps like this for them. I'd also prefer to have no copy ctor at all, than one which behaves unlike a normal copy. If people are going to have to bear in mind that Vector cannot actually be copied, then they shouldn't use copy syntax to not-copy it.
The issue of unnecessary copies in C++03 isn't a new one and IMO it doesn't require a novel solution. Many C++ programmers already know how to take advantage of swap and copy elision, and those who don't know how to avoid unnecessary copies are better off learning to do it the normal way, than learning to do it a unique way demanded by your one specific class.
With the insight from comments/answers, I realized that my current approach is not a good idea to deal with the things.
I have come up with a changed designed where I try to simulate the "move" operation using swap() method (consider them interchangeable in this context).
For any class or container, which wants to make faster copying (i.e. move by swapping) should inherit below class (directly copy pasting from the real file):
/*
* An empty CRTP base class for the classes which are allowing move sematics (effectively swap)
* A given class `X` must implement `void swap(X&);` method for the movement (i.e. content swapping)
* For example, `X` is deriving this class (i.e. `class X : public Movable<X> ...`)
* ... below is an illustration for how to transfer contents of an `X` object to another
* `X o1; ... X o2(o1.move()); // contents of o1 is now moved to o2`
*/
template<typename Derived>
class Movable
{
/*
* Empty constructor for normal behavior
*/
public: Movable ()
{}
/*
* Copy constructor which does nothing; without this compiler errors out !
*/
public: Movable (const Movable ©)
{}
/*
* Move constructor which will effectively call `Derived::swap()` method
* After this, the contents of the object will be moved to each other
* For syntactic sugar, it has been made `explicit`
*/
public: explicit Movable (Movable &orig)
{
(*this)(orig);
}
/*
* Moving while Not initializing object, one need to use `operator ()` and not `operator =`
* If `operator =` is used then simply `move()` part will not happen; i.e. below 2 are same:
* `obj1 = obj2.move();` and `obj1 = obj2;`
*/
public: void operator () (Movable &orig)
{
static_cast<Derived*>(this)->swap(static_cast<Derived&>(orig));
}
/*
* This method is called from `Derived` class when move sematics is intended
*/
public: Movable& move ()
{
return *this;
}
};
Here how it's supposed to be deployed:
template<typename T>
struct Vector : std::vector<T>,
Movable<Vector<T> > // inherit as CRTP base
{
// ... other methods
typedef Movable<Vector<T> > Movable_;
Vector (Movable_ &orig) : Movable_(orig) {} // Declare a constructor
};
Here how it's supposed to be used:
Vector<A> vA1(100); // vA1 is allocated A[100]
Vector<A> vA2 = vA1; // normal copying (no change)
vA2 = vA1; // normal assignment (no change)
Vector<A> vA3(vA1.move()); // <------- "moves" contents from 'vA1' to 'vA3'
vA1(vA2.move()); // <------- "moves" contents from 'vA2' to 'vA1'
vA2 = vA3.move(); // normal copying from 'vA3' to 'vA2' ('vA3' unaffected)