1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2010-2016.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/move for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef BOOST_MOVE_MOVE_HELPERS_HPP
13 #define BOOST_MOVE_MOVE_HELPERS_HPP
14 
15 #ifndef BOOST_CONFIG_HPP
16 #  include <boost/config.hpp>
17 #endif
18 #
19 #if defined(BOOST_HAS_PRAGMA_ONCE)
20 #  pragma once
21 #endif
22 
23 #include <boost/move/core.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/move/detail/type_traits.hpp>
26 
27 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
28 
29 #define BOOST_MOVE_CATCH_CONST(U)  \
30    typename ::boost::move_detail::if_< ::boost::move_detail::is_class<U>, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type
31 #define BOOST_MOVE_CATCH_RVALUE(U)\
32    typename ::boost::move_detail::if_< ::boost::move_detail::is_class<U>, BOOST_RV_REF(U), ::boost::move_detail::nat>::type
33 #define BOOST_MOVE_CATCH_FWD(U) BOOST_FWD_REF(U)
34 #else
35 #define BOOST_MOVE_CATCH_CONST(U)  const U &
36 #define BOOST_MOVE_CATCH_RVALUE(U) U &&
37 #define BOOST_MOVE_CATCH_FWD(U)    U &&
38 #endif
39 
40 ////////////////////////////////////////
41 //
42 // BOOST_MOVE_CONVERSION_AWARE_CATCH
43 //
44 ////////////////////////////////////////
45 
46 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
47 
48    template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
49    struct boost_move_conversion_aware_catch_1
50       : public ::boost::move_detail::enable_if_and
51                         < RETURN_VALUE
52                         , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
53                         , ::boost::move_detail::is_class<TYPE>
54                         , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
55                         >
56    {};
57 
58    template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class TYPE>
59    struct boost_move_conversion_aware_catch_2
60       : public ::boost::move_detail::disable_if_or
61                         < RETURN_VALUE
62                         , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
63                         , ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
64                         , ::boost::move_detail::and_
65                                     < ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
66                                     , ::boost::move_detail::is_class<BOOST_MOVE_TEMPL_PARAM>
67                                     >
68                         >
69    {};
70 
71    #define BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
72       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
73       {  return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
74       \
75       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
76       {  return FWD_FUNCTION(::boost::move(x));  }\
77       \
78       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(TYPE &x)\
79       {  return FWD_FUNCTION(const_cast<const TYPE &>(x)); }\
80    //
81    #if defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
82       #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
83          BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
84          \
85          template<class BOOST_MOVE_TEMPL_PARAM>\
86          BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
87             typename boost_move_conversion_aware_catch_1< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
88          { return FWD_FUNCTION(u); }\
89          \
90          template<class BOOST_MOVE_TEMPL_PARAM>\
91          BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u,\
92             typename boost_move_conversion_aware_catch_2< ::boost::move_detail::nat, BOOST_MOVE_TEMPL_PARAM, TYPE>::type* = 0)\
93          {\
94             TYPE t((u));\
95             return FWD_FUNCTION(::boost::move(t));\
96          }\
97       //
98    #else
99       #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
100          BOOST_MOVE_CONVERSION_AWARE_CATCH_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
101          \
102          template<class BOOST_MOVE_TEMPL_PARAM>\
103          BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
104             PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
105          { return FWD_FUNCTION(u); }\
106          \
107          template<class BOOST_MOVE_TEMPL_PARAM>\
108          BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, TYPE>::type\
109             PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
110          {\
111             TYPE t((u));\
112             return FWD_FUNCTION(::boost::move(t));\
113          }\
114       //
115    #endif
116 #elif (defined(_MSC_VER) && (_MSC_VER == 1600))
117 
118    #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
119       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
120       {  return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\
121       \
122       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
123       {  return FWD_FUNCTION(::boost::move(x));  }\
124       \
125       template<class BOOST_MOVE_TEMPL_PARAM>\
126       BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c\
127                         < !::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value\
128                         , RETURN_VALUE >::type\
129       PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\
130       {\
131          TYPE t((u));\
132          return FWD_FUNCTION(::boost::move(t));\
133       }\
134    //
135 
136 #else    //BOOST_NO_CXX11_RVALUE_REFERENCES
137 
138    #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\
139       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\
140       {  return FWD_FUNCTION(x); }\
141       \
142       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
143       {  return FWD_FUNCTION(::boost::move(x));  }\
144    //
145 
146 #endif   //BOOST_NO_CXX11_RVALUE_REFERENCES
147 
148 ////////////////////////////////////////
149 //
150 // BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
151 //
152 ////////////////////////////////////////
153 
154 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
155 
156    template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
157    struct boost_move_conversion_aware_catch_1arg_1
158       : public ::boost::move_detail::enable_if_and
159                         < RETURN_VALUE
160                         , ::boost::move_detail::not_< ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> >
161                         , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
162                         , ::boost::has_move_emulation_disabled<BOOST_MOVE_TEMPL_PARAM>
163                         >
164    {};
165 
166    template<class RETURN_VALUE, class BOOST_MOVE_TEMPL_PARAM, class UNLESS_CONVERTIBLE_TO, class TYPE>
167    struct boost_move_conversion_aware_catch_1arg_2
168       : public ::boost::move_detail::disable_if_or
169                         < RETURN_VALUE
170                         , ::boost::move_detail::is_same_or_convertible< BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>
171                         , ::boost::move_detail::is_rv_impl<BOOST_MOVE_TEMPL_PARAM>
172                         , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>
173                         >
174    {};
175 
176    #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
177       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
178       {  return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
179       \
180       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
181       {  return FWD_FUNCTION(arg1, ::boost::move(x));  }\
182       \
183       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, TYPE &x)\
184       {  return FWD_FUNCTION(arg1, const_cast<const TYPE &>(x)); }\
185    //
186    #if defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
187       #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
188          BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
189          \
190          template<class BOOST_MOVE_TEMPL_PARAM>\
191          BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
192             typename boost_move_conversion_aware_catch_1arg_1<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
193          { return FWD_FUNCTION(arg1, u); }\
194          \
195          template<class BOOST_MOVE_TEMPL_PARAM>\
196          BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u,\
197             typename boost_move_conversion_aware_catch_1arg_2<void, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type* = 0)\
198          {\
199             TYPE t((u));\
200             return FWD_FUNCTION(arg1, ::boost::move(t));\
201          }\
202       //
203    #else
204       #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
205          BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG_COMMON(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
206          \
207          template<class BOOST_MOVE_TEMPL_PARAM>\
208          BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_1arg_1<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
209             PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
210          { return FWD_FUNCTION(arg1, u); }\
211          \
212          template<class BOOST_MOVE_TEMPL_PARAM>\
213          BOOST_MOVE_FORCEINLINE typename boost_move_conversion_aware_catch_1arg_2<RETURN_VALUE, BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO, TYPE>::type\
214             PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
215          {\
216             TYPE t((u));\
217             return FWD_FUNCTION(arg1, ::boost::move(t));\
218          }\
219       //
220    #endif
221 
222 #elif (defined(_MSC_VER) && (_MSC_VER == 1600))
223 
224    #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
225       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
226       {  return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
227       \
228       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
229       {  return FWD_FUNCTION(arg1, ::boost::move(x));  }\
230       \
231       template<class BOOST_MOVE_TEMPL_PARAM>\
232       BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::disable_if_or\
233                         < RETURN_VALUE \
234                         , ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM> \
235                         , ::boost::move_detail::is_same_or_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO> \
236                         >::type\
237       PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\
238       {\
239          TYPE t((u));\
240          return FWD_FUNCTION(arg1, ::boost::move(t));\
241       }\
242    //
243 
244 #else
245 
246    #define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\
247       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\
248       {  return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\
249       \
250       BOOST_MOVE_FORCEINLINE RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \
251       {  return FWD_FUNCTION(arg1, ::boost::move(x));  }\
252    //
253 
254 #endif
255 
256 #endif //#ifndef BOOST_MOVE_MOVE_HELPERS_HPP
257