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 *************************************************************/
34template <class _Tp>
35class __move_source {
36public:
37  explicit __move_source (_Tp &_src) : _M_data(_src)
38  {}
39
40  _Tp& get() const
41  { return _M_data; }
42private:
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.
51template <class _Tp>
52struct __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 */
85template <class _Tp>
86struct _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
99template <class _Tp>
100inline _STLP_TYPENAME_ON_RETURN_TYPE _MoveSourceTraits<_Tp>::_Type
101_AsMoveSource (_Tp &src) {
102  typedef typename _MoveSourceTraits<_Tp>::_Type _SrcType;
103  return _SrcType(src);
104}
105
106//Helper structs used for many class.
107template <class _Tp>
108struct __move_traits_aux {
109  typedef typename __move_traits<_Tp>::implemented implemented;
110  typedef typename __move_traits<_Tp>::complete complete;
111};
112
113template <class _Tp1, class _Tp2>
114struct __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 */
128template <class _Tp>
129struct __move_traits_help {
130  typedef __true_type implemented;
131  typedef typename __move_traits<_Tp>::complete complete;
132};
133
134template <class _Tp1, class _Tp2>
135struct __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
145template <class _Tp1, class _Tp2>
146struct __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