topic "Moveable";
[2 $$0,0#00000000000000000000000000000000:Default]
[l288;i704;a17;O9;~~~.992;2 $$1,0#10431211400427159095818037425705:param]
[a83;*R6 $$2,5#31310162474203024125188417583966:caption]
[b83;*2 $$3,5#07864147445237544204411237157677:title]
[b167;a42;C2 $$4,6#40027414424643823182269349404212:item]
[b42;a42;2 $$5,5#45413000475342174754091244180557:text]
[l288;a17;2 $$6,6#27521748481378242620020725143825:desc]
[l321;t246;C@5;1 $$7,7#20902679421464641399138805415013:code]
[b2503;2 $$8,0#65142375456100023862071332075487:separator]
[*@(0.0.255)2 $$9,0#83433469410354161042741608181528:base]
[t4167;C2 $$10,0#37138531426314131251341829483380:class]
[l288;a17;*1 $$11,11#70004532496200323422659154056402:requirement]
[i417;b42;a42;O9;~~~.416;2 $$12,12#10566046415157235020018451313112:tparam]
[b167;C2 $$13,13#92430459443460461911108080531343:item1]
[i288;a42;O9;C2 $$14,14#77422149456609303542238260500223:item2]
[*@2$(0.128.128)2 $$15,15#34511555403152284025741354420178:NewsDate]
[l321;*C$7;2 $$16,16#03451589433145915344929335295360:result]
[l321;b83;a83;*C$7;2 $$17,17#07531550463529505371228428965313:result`-line]
[l160;t4167;*C+117 $$18,5#88603949442205825958800053222425:package`-title]
[{_}%EN-US 
[s2; Moveable&]
[s5; First important node: U`+`+ Moveable is not to be confused with 
C`+`+ standard library move semantics.&]
[s5; Moveable concept represents basic requirement for types stored 
in Vector flavor of containers (namely Vector, BiVector, Index, 
VectorMap, InVector, SortedIndex, SortedVectorMap). To explain 
what it is and why it is so important let us first create a very 
primitive Vector`-like container template&]
[s7; template <class T>&]
[s7; class SimpleVector `{&]
[s7; -|T  `*vector;&]
[s7; -|int capacity;&]
[s7; -|int items;&]
[s7; &]
[s7; -|void [* Expand()] `{&]
[s7; -|-|capacity `= max(1, 2 `* capacity);&]
[s7; -|-|T `*newvector `= (T `*) new char`[capacity `* sizeof(T)`];&]
[s7; -|-|for(int i `= 0; i < items; i`+`+) `{&]
[s7; -|-|-|[* new(newvector`[i`]) T(vector`[i`])];&]
[s7; -|-|-|[* vector`[i`].T`::`~T();]&]
[s7; -|-|`}&]
[s7; -|-|delete`[`] (char `*) vector;&]
[s7; -|-|vector `= newvector;&]
[s7; -|`}&]
[s7; public:&]
[s7; -|void Add(const T`& x) `{&]
[s7; -|-|if(items >`= capacity) [* Expand()];&]
[s7; -|-|new(vector`[items`+`+`]) T(x);&]
[s7; -|`}&]
[s7; -|T`& operator`[`](int i) `{ return vector`[i`]; `}&]
[s7; -|SimpleVector() `{&]
[s7; -|-|vector `= NULL;&]
[s7; -|-|capacity `= items `= 0;&]
[s7; -|`}&]
[s7; -|`~SimpleVector() `{&]
[s7; -|-|for(int i `= 0; i < items; i`+`+)&]
[s7; -|-|-|vector`[i`].T`::`~T();&]
[s7; -|-|delete`[`] (char `*)vector;&]
[s7; -|`}&]
[s7; `};&]
[s5; This [* SimpleVector] stores added elements in the [* vector] member 
field. If there is no more empty storage space left in [* vector], 
[* SimpleVector] simply doubles its capacity using [* Expand] method. 
This method is what interests us `- because [* Expand ]requires 
means to copy values of elements from the original memory area 
to the newly allocated one. The version above uses placement 
new and copy constructor for this purpose. This also means that 
[* SimpleVector] requires T to have copy constructor (in standard 
C`+`+ library terms: it must be [/ copy`-constructible]). Now let 
us create a typical element that can be stored in such container&]
[s7; class SimpleString `{&]
[s7; -|char `*text;&]
[s7; public:&]
[s7; -|SimpleString(const char `*txt) `{&]
[s7; -|-|text `= new char`[strlen(txt)`+1`];&]
[s7; -|-|strcpy(text, txt);&]
[s7; -|`}&]
[s7; -|SimpleString(const SimpleString`& s) `{&]
[s7; -|-|text `= new char`[strlen(s.text)`+1`];&]
[s7; -|-|strcpy(text, s.text);&]
[s7; -|`}&]
[s7; -|void operator`=(const SimpleString`& s) `{&]
[s7; -|-|delete`[`] text;&]
[s7; -|-|text `= new char`[strlen(s.text)`+1`];&]
[s7; -|-|strcpy(text, s.text);-|-|&]
[s7; -|`}&]
[s7; -|`~SimpleString() `{&]
[s7; -|-|delete`[`] text;&]
[s7; -|`}&]
[s7; `};&]
[s5; and see what happens when [* SimpleVector] of [* SimpleString]s 
is expanded: First, copies of all elements are created, that means 
allocating new storage for [* text] member of new element and copying 
source [* text] to it using [* strcpy]. A moment later, [* Expand] 
invokes destructor for element, thus deleting all [* text]s in 
the original elements. Does not it seem we are wasting a lot 
of CPU cycles just to make copies of things that we throw away 
a moment later anyway? What if instead of making copies we could 
find a way to transfer original elements`' [* text] members to 
new elements and somehow disallow [* delete`[`] text] in destructor? 
See how primitive it can be:&]
[s7; template <class T>&]
[s7; class SimpleVector `{&]
[s7; -|T  `*vector;&]
[s7; -|int capacity;&]
[s7; -|int items;&]
[s7; &]
[s7; -|void Expand() `{&]
[s7; -|-|capacity `= max(1, 2 `* capacity);&]
[s7; -|-|T `*newvector `= (T `*) new char`[capacity `* sizeof(T)`];&]
[s7; -|-|[* memcpy(newvector, vector, items `* sizeof(T));]&]
[s7; -|-|delete`[`](char `*)vector;&]
[s7; -|-|vector `= newvector;&]
[s7; -|`}&]
[s7; public:&]
[s7; -|void Add(const T`& x) `{&]
[s7; -|-|if(items >`= capacity) Expand();&]
[s7; -|-|new(vector`[items`+`+`]) T(x);&]
[s7; -|`}&]
[s7; -|SimpleVector() `{&]
[s7; -|-|vector `= NULL;&]
[s7; -|-|capacity `= items `= 0;&]
[s7; -|`}&]
[s7; -|`~SimpleVector() `{&]
[s7; -|-|for(int i `= 0; i < items; i`+`+)&]
[s7; -|-|-|vector`[i`].T`::`~T();&]
[s7; -|-|delete`[`] (char `*)vector;&]
[s7; -|`}&]
[s7; `};&]
[s5; For the moment please ignore fact that by using memcpy to move 
non`-POD types we are violating C`+`+ standard (we will discuss 
it later). Now, what we get here is exactly what we wanted `- 
instead of a series of copy construction and destruction we simply 
copy raw binary data to the new location. This way we simply 
transfer the old value in the [* text ]member of elements into 
the new expanded [* vector]. We need to invoke neither copy constructor 
nor destructor when expanding vector. Not a single CPU cycle 
is lost.&]
[s5; The types that can be moved in memory using memcpy are called 
[*/ moveable.]&]
[s5; Clearly not all types are moveable. Being moveable has a lot 
to do with [/ not] storing references to the object itself or to 
it`'s parts. E.g.&]
[s7; struct Link `{&]
[s7; -|Link `*prev;&]
[s7; public:&]
[s7; -|Link()        `{ prev `= NULL; `}&]
[s7; -|Link(Link `*p) `{ prev `= p; `}&]
[s7; `};&]
[s5; is [* not] moveable, because memcpy`-ing to a new location would 
break the existing links. All of the following requirements should 
be fullfilled for moveable types:&]
[s5;i150;O0; It does not have any virtual method nor virtual base 
class.&]
[s5;i150;O0; Base classes (if any) and any instance member variables 
are moveable.&]
[s5;i150;O0; No references or pointers are stored to the object itself 
or to subobjects in the methods of the type, into variables that 
exist after the method finishes execution. &]
[s5; Fundamental types fulfills these requirements so they are moveable.&]
[s5; Example:&]
[s7; struct Foo;&]
[s7; &]
[s7; Foo `*global`_foo;&]
[s0; &]
[s7; struct Foo `{&]
[s7; -|int a;&]
[s7; -|Foo `*foo;&]
[s7; -|int `*ptr;&]
[s7; public:&]
[s7; -|void Set(Foo `* f) `{&]
[s7; -|-|foo `= f;&]
[s7; -|`}&]
[s7; -|void Ok1() `{&]
[s7; -|-|Foo `*x `= this;&]
[s7; -|// local variable will not exist outside method&]
[s7; -|// `-> does not prevent Foo from being moveable&]
[s7; -|`}&]
[s7; -|void Ok2() `{&]
[s7; -|-|memset(`&a, 0, sizeof(int));&]
[s7; -|// pointer will not exist outside method&]
[s7; -|// `-> does not prevent Foo from being moveable&]
[s7; -|`}&]
[s7; -|void Bad1() `{&]
[s7; -|-|foo `= this;&]
[s7; -|// member variable foo exists outside method&]
[s7; -|// `-> makes Foo non`-moveable&]
[s7; -|`}&]
[s7; -|void Bad2() `{&]
[s7; -|-|ptr `= `&a;&]
[s7; -|// pointer to subobject stored, ptr exists outside method&]
[s7; -|// `-> makes Foo non`-moveable&]
[s7; -|`}&]
[s7; -|void Bad3() `{&]
[s7; -|-|global`_foo `= this;&]
[s7; -|// pointer stored to global variable&]
[s7; -|// `-> makes Foo non`-moveable&]
[s7; -|`}&]
[s7; -|void Bad4(Foo`& another) `{&]
[s7; -|-|another.Set(this);&]
[s7; -|// pointer stored indirectly in object that exist outside method&]
[s7; -|// `-> makes Foo non`-moveable&]
[s7; -|`}&]
[s7; `};&]
[s5; These requirements satisfies fairly large number of types, incidentally 
most of the types you ever wanted to store in a container of 
elements of a single type are moveable. Most important, all NTL 
containers [* are ]moveable.&]
[s5; Now we have an effective method how to organize the storing 
of elements in containers. We have to deal with the fact that 
being moveable is part of an object`'s interface, and we should 
ensure that only movable elements are stored into NTL containers. 
For this we need a way to declare at compile time that a certain 
type is moveable and also a way to check it.&]
[s5; To achieve this goal, you can mark moveable types by deriving 
them from the [* Moveable] template class e.g.:&]
[s7; class SimpleString : Moveable<SimpleString> `{ ... `}&]
[s5; Alternatively the [* NTL`_MOVEABLE ]macro can be used to mark 
types as moveable if the class interface can not be changed, 
such as in:&]
[s7; NTL`_MOVEABLE(std`::string);&]
[s5; Now that we can mark types as moveable, we need a way to check 
a type for being moveable. This is done by adding the line:&]
[s7; AssertMoveable<T>()&]
[s5; to one of the methods of a template that gets compiled for any 
template argument `- the destructor is the most obvious place. 
The AssertMovable function is defined only if [* T] is marked as 
moveable, so it results in compilation error for non`-moveable 
T types.&]
[s5; Finally, time has come to deal with the C`+`+ standard. Current 
C`+`+ defines memcpy only for POD types. The moveable concept 
requires memcpy of non`-POD types to be defined. In fact, difference 
between POD and moveable non`-POD types is the existence of constructors 
and non`-virtual destructor. To get things work, all we need 
is that the result of memcpy`-ing non`-POD type [* T ]is same as 
memcpy`-ing the POD [* T1 ]type which you would get by removing 
the destructor and the constructors from [* T]. While this operation 
is still undefined by C`+`+, it is really hard to imagine an 
optimal C`+`+ implementation that would break this rule. Indeed, 
all current implementation we have met so far support moveable 
semantics in the way we have defined here. Performance and other 
gains realized by using the moveable concept are too big to ignore.]]