1 /*
2  *
3  * Copyright (c) 2003
4  * Francois Dumont
5  *
6  * This material is provided "as is", with absolutely no warranty expressed
7  * or implied. Any use is at your own risk.
8  *
9  * Permission to use or copy this software for any purpose is hereby granted
10  * without fee, provided the above notices are retained on all copies.
11  * Permission to modify the code and to distribute modified code is granted,
12  * provided the above notices are retained, and a notice that the code was
13  * modified is included with the above copyright notice.
14  *
15  */
16 
17 #ifndef _STLP_MOVE_CONSTRUCT_FWK_H
18 #define _STLP_MOVE_CONSTRUCT_FWK_H
19 
20 #ifndef _STLP_TYPE_TRAITS_H
21 #  include <stl/type_traits.h>
22 #endif
23 
24 _STLP_BEGIN_NAMESPACE
25 
26 /*************************************************************
27  * Move constructor framework
28  *************************************************************/
29 
30 /*************************************************************
31  *Partial move:
32  *The source HAS to be a valid instance after the move!
33  *************************************************************/
34 template <class _Tp>
35 class __move_source {
36 public:
__move_source(_Tp & _src)37   explicit __move_source (_Tp &_src) : _M_data(_src)
38   {}
39 
get()40   _Tp& get() const
41   { return _M_data; }
42 private:
43   _Tp &_M_data;
44 
45   //We explicitely forbid assignment to avoid warning:
46   typedef __move_source<_Tp> _Self;
47   _Self& operator = (_Self const&);
48 };
49 
50 //Class used to signal move constructor support, implementation and type.
51 template <class _Tp>
52 struct __move_traits {
53   /*
54    * implemented tells if a the special move constructor has to be called or the classic
55    * copy constructor is just fine. Most of the time the copy constructor is fine only
56    * if the following info is true.
57    */
58 #if defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) && \
59    !defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) && \
60    !defined (_STLP_NO_MOVE_SEMANTIC)
61   typedef typename _IsSTLportClass<_Tp>::_Ret implemented;
62 #else
63   typedef __false_type implemented;
64 #endif
65   /*
66    * complete tells if the move is complete or partial, that is to say, does the source
67    * needs to be destroyed once it has been moved.
68    */
69 #  if defined (__BORLANDC__) && (__BORLANDC__ >= 0x564)
70   typedef __type_traits<_Tp>::has_trivial_destructor _TpMoveComplete;
71   typedef typename __bool2type<__type2bool<_TpMoveComplete>::_Ret>::_Ret complete;
72 #  else
73   typedef typename __type_traits<_Tp>::has_trivial_destructor complete;
74 #  endif
75 };
76 
77 _STLP_MOVE_TO_PRIV_NAMESPACE
78 
79 /*
80  * This struct should never be used if the user has not explicitely stipulated
81  * that its class support the full move concept. To check that the return type
82  * in such a case will be __invalid_source<_Tp> to generate a compile error
83  * revealing the configuration problem.
84  */
85 template <class _Tp>
86 struct _MoveSourceTraits {
87   typedef typename __move_traits<_Tp>::implemented _MvImpRet;
88 #if defined (__BORLANDC__)
89   typedef typename __selectT<_MvImpRet,
90 #else
91   enum {_MvImp = __type2bool<_MvImpRet>::_Ret};
92   typedef typename __select<_MvImp,
93 #endif
94                             __move_source<_Tp>,
95                             _Tp const&>::_Ret _Type;
96 };
97 
98 //The helper function
99 template <class _Tp>
100 inline _STLP_TYPENAME_ON_RETURN_TYPE _MoveSourceTraits<_Tp>::_Type
_AsMoveSource(_Tp & src)101 _AsMoveSource (_Tp &src) {
102   typedef typename _MoveSourceTraits<_Tp>::_Type _SrcType;
103   return _SrcType(src);
104 }
105 
106 //Helper structs used for many class.
107 template <class _Tp>
108 struct __move_traits_aux {
109   typedef typename __move_traits<_Tp>::implemented implemented;
110   typedef typename __move_traits<_Tp>::complete complete;
111 };
112 
113 template <class _Tp1, class _Tp2>
114 struct __move_traits_aux2 {
115   typedef __move_traits<_Tp1> _MoveTraits1;
116   typedef __move_traits<_Tp2> _MoveTraits2;
117 
118   typedef typename _Lor2<typename _MoveTraits1::implemented,
119                          typename _MoveTraits2::implemented>::_Ret implemented;
120   typedef typename _Land2<typename _MoveTraits1::complete,
121                           typename _MoveTraits2::complete>::_Ret complete;
122 };
123 
124 /*
125  * Most of the time a class implement a move constructor but its use depends
126  * on a third party, this is what the following struct are for.
127  */
128 template <class _Tp>
129 struct __move_traits_help {
130   typedef __true_type implemented;
131   typedef typename __move_traits<_Tp>::complete complete;
132 };
133 
134 template <class _Tp1, class _Tp2>
135 struct __move_traits_help1 {
136   typedef __move_traits<_Tp1> _MoveTraits1;
137   typedef __move_traits<_Tp2> _MoveTraits2;
138 
139   typedef typename _Lor2<typename _MoveTraits1::implemented,
140                          typename _MoveTraits2::implemented>::_Ret implemented;
141   typedef typename _Land2<typename _MoveTraits1::complete,
142                           typename _MoveTraits2::complete>::_Ret complete;
143 };
144 
145 template <class _Tp1, class _Tp2>
146 struct __move_traits_help2 {
147   typedef __move_traits<_Tp1> _MoveTraits1;
148   typedef __move_traits<_Tp2> _MoveTraits2;
149 
150   typedef __true_type implemented;
151   typedef typename _Land2<typename _MoveTraits1::complete,
152                           typename _MoveTraits2::complete>::_Ret complete;
153 };
154 
155 _STLP_MOVE_TO_STD_NAMESPACE
156 
157 _STLP_END_NAMESPACE
158 
159 #endif /* _STLP_MOVE_CONSTRUCT_FWK_H */
160