blob: 6fec1071e3d7550b60a179d52e7ff6f2a6d0dc86 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001
2// (C) Copyright Tobias Schwinger
3//
4// Use modification and distribution are subject to the boost Software License,
5// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).
6
7//------------------------------------------------------------------------------
8
Jeff Thompson3d613fd2013-10-15 15:39:04 -07009#ifndef NDNBOOST_FT_COMPONENTS_HPP_INCLUDED
10#define NDNBOOST_FT_COMPONENTS_HPP_INCLUDED
Jeff Thompsona28eed82013-08-22 16:21:10 -070011
12#include <cstddef>
13
14#include <ndnboost/config.hpp>
15
16#include <ndnboost/detail/workaround.hpp>
17#include <ndnboost/mpl/aux_/lambda_support.hpp>
18#include <ndnboost/type_traits/detail/template_arity_spec.hpp>
19
20#include <ndnboost/type_traits/integral_constant.hpp>
21
22#include <ndnboost/mpl/if.hpp>
23#include <ndnboost/mpl/integral_c.hpp>
24#include <ndnboost/mpl/vector/vector0.hpp>
25
Jeff Thompson3d613fd2013-10-15 15:39:04 -070026#if NDNBOOST_WORKAROUND(__BORLANDC__, <= 0x565)
Jeff Thompsona28eed82013-08-22 16:21:10 -070027# include <ndnboost/type_traits/remove_cv.hpp>
28
29# include <ndnboost/mpl/identity.hpp>
30# include <ndnboost/mpl/bitand.hpp>
31# include <ndnboost/mpl/vector/vector10.hpp>
32# include <ndnboost/mpl/front.hpp>
33# include <ndnboost/mpl/begin.hpp>
34# include <ndnboost/mpl/advance.hpp>
35# include <ndnboost/mpl/iterator_range.hpp>
36# include <ndnboost/mpl/joint_view.hpp>
37# include <ndnboost/mpl/equal_to.hpp>
38# include <ndnboost/mpl/copy.hpp>
39# include <ndnboost/mpl/front_inserter.hpp>
40
41# include <ndnboost/function_types/detail/classifier.hpp>
42#endif
43
Jeff Thompson3d613fd2013-10-15 15:39:04 -070044#ifndef NDNBOOST_FT_NO_CV_FUNC_SUPPORT
Jeff Thompsona28eed82013-08-22 16:21:10 -070045# include <ndnboost/mpl/remove.hpp>
46#endif
47
48#include <ndnboost/function_types/config/config.hpp>
49
Jeff Thompson3d613fd2013-10-15 15:39:04 -070050#ifndef NDNBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
51# if NDNBOOST_FT_MAX_ARITY < 10
Jeff Thompsona28eed82013-08-22 16:21:10 -070052# include <ndnboost/mpl/vector/vector10.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -070053# elif NDNBOOST_FT_MAX_ARITY < 20
Jeff Thompsona28eed82013-08-22 16:21:10 -070054# include <ndnboost/mpl/vector/vector20.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -070055# elif NDNBOOST_FT_MAX_ARITY < 30
Jeff Thompsona28eed82013-08-22 16:21:10 -070056# include <ndnboost/mpl/vector/vector30.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -070057# elif NDNBOOST_FT_MAX_ARITY < 40
Jeff Thompsona28eed82013-08-22 16:21:10 -070058# include <ndnboost/mpl/vector/vector40.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -070059# elif NDNBOOST_FT_MAX_ARITY < 50
Jeff Thompsona28eed82013-08-22 16:21:10 -070060# include <ndnboost/mpl/vector/vector50.hpp>
61# endif
62#else
63# include <ndnboost/function_types/detail/classifier.hpp>
64#endif
65
66#include <ndnboost/function_types/detail/class_transform.hpp>
67#include <ndnboost/function_types/property_tags.hpp>
68
69// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70
71namespace ndnboost
72{
73 namespace function_types
74 {
75
76 using mpl::placeholders::_;
77
78 template< typename T, typename ClassTypeTransform = add_reference<_> >
79 struct components;
80
81 namespace detail
82 {
83 template<typename T, typename L> struct components_impl;
Jeff Thompson3d613fd2013-10-15 15:39:04 -070084#if NDNBOOST_WORKAROUND(__BORLANDC__, <= 0x565)
Jeff Thompsona28eed82013-08-22 16:21:10 -070085 template<typename T, typename OrigT, typename L> struct components_bcc;
86#endif
87 }
88
89 template<typename T, typename ClassTypeTransform>
90 struct components
Jeff Thompson3d613fd2013-10-15 15:39:04 -070091#if !NDNBOOST_WORKAROUND(__BORLANDC__, <= 0x565)
Jeff Thompsona28eed82013-08-22 16:21:10 -070092 : detail::components_impl<T, ClassTypeTransform>
93#else
94 : detail::components_bcc<typename remove_cv<T>::type,T,
95 ClassTypeTransform>
96#endif
97 {
98 typedef components<T,ClassTypeTransform> type;
99
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700100 NDNBOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700101 };
102
103// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104
105 namespace detail {
106
107 struct components_mpl_sequence_tag;
108
109 struct components_non_func_base
110 {
111 typedef mpl::vector0<> types;
112 typedef void function_arity;
113
114 typedef detail::constant<0> bits;
115 typedef detail::constant<0> mask;
116
117 typedef components_mpl_sequence_tag tag;
118 };
119
120 template
121 < typename Components
122 , typename IfTagged
123 , typename ThenTag
124 , typename DefaultBase = components_non_func_base
125 >
126 struct retagged_if
127 : mpl::if_
128 < detail::represents_impl<Components, IfTagged>
129 , detail::changed_tag<Components,IfTagged,ThenTag>
130 , DefaultBase
131 >::type
132 { };
133
134 // We detect plain function types and function references as function
135 // pointers by recursive instantiation of components_impl.
136 // The third specialization of components_impl makes sure the recursion
137 // terminates (when adding pointers).
138 template<typename T, typename L>
139 struct components_impl
140 : detail::retagged_if
141 < detail::components_impl<T*,L>
142 , pointer_tag, /* --> */ function_tag >
143 { };
144 template<typename T, typename L>
145 struct components_impl<T&, L>
146 : detail::retagged_if
147 < detail::components_impl<T*,L>
148 , pointer_tag, /* --> */ reference_tag >
149 { };
150
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700151#if !NDNBOOST_FT_NO_CV_FUNC_SUPPORT
Jeff Thompsona28eed82013-08-22 16:21:10 -0700152 // Retry the type with a member pointer attached to detect cv functions
153 class a_class;
154
155 template<typename Base, typename T, typename L>
156 struct cv_func_base
157 : detail::retagged_if<Base,member_pointer_tag,function_tag>
158 {
159 typedef typename
160 mpl::remove
161 < typename Base::types
162 , typename detail::class_transform<a_class,L>::type>::type
163 types;
164 };
165
166 template<typename T, typename L>
167 struct components_impl<T*, L>
168 : mpl::if_
169 < detail::represents_impl< detail::components_impl<T a_class::*, L>
170 , member_pointer_tag >
171 , detail::cv_func_base< detail::components_impl<T a_class::*, L>, T, L>
172 , components_non_func_base
173 >::type
174 { };
175
176 template<typename T, typename L>
177 struct components_impl<T a_class::*, L>
178 : components_non_func_base
179 { };
180#else
181 template<typename T, typename L>
182 struct components_impl<T*, L>
183 : components_non_func_base
184 { };
185#endif
186
187 template<typename T, typename L>
188 struct components_impl<T* const, L>
189 : components_impl<T*,L>
190 { };
191
192 template<typename T, typename L>
193 struct components_impl<T* volatile, L>
194 : components_impl<T*,L>
195 { };
196
197 template<typename T, typename L>
198 struct components_impl<T* const volatile, L>
199 : components_impl<T*,L>
200 { };
201
202 template<typename T, typename L>
203 struct components_impl<T const, L>
204 : components_impl<T,L>
205 { };
206
207 template<typename T, typename L>
208 struct components_impl<T volatile, L>
209 : components_impl<T,L>
210 { };
211
212 template<typename T, typename L>
213 struct components_impl<T const volatile, L>
214 : components_impl<T,L>
215 { };
216
217
218 template<typename T, class C>
219 struct member_obj_ptr_result
220 { typedef T & type; };
221
222 template<typename T, class C>
223 struct member_obj_ptr_result<T, C const>
224 { typedef T const & type; };
225
226 template<typename T, class C>
227 struct member_obj_ptr_result<T, C volatile>
228 { typedef T volatile & type; };
229
230 template<typename T, class C>
231 struct member_obj_ptr_result<T, C const volatile>
232 { typedef T const volatile & type; };
233
234 template<typename T, class C>
235 struct member_obj_ptr_result<T &, C>
236 { typedef T & type; };
237
238 template<typename T, class C>
239 struct member_obj_ptr_result<T &, C const>
240 { typedef T & type; };
241
242 template<typename T, class C>
243 struct member_obj_ptr_result<T &, C volatile>
244 { typedef T & type; };
245
246 template<typename T, class C>
247 struct member_obj_ptr_result<T &, C const volatile>
248 { typedef T & type; };
249
250 template<typename T, class C, typename L>
251 struct member_obj_ptr_components
252 : member_object_pointer_base
253 {
254 typedef function_types::components<T C::*, L> type;
255 typedef components_mpl_sequence_tag tag;
256
257 typedef mpl::integral_c<std::size_t,1> function_arity;
258
259 typedef mpl::vector2< typename detail::member_obj_ptr_result<T,C>::type,
260 typename detail::class_transform<C,L>::type > types;
261 };
262
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700263#if !NDNBOOST_WORKAROUND(__BORLANDC__, <= 0x565)
264# define NDNBOOST_FT_variations NDNBOOST_FT_pointer|NDNBOOST_FT_member_pointer
Jeff Thompsona28eed82013-08-22 16:21:10 -0700265
266 template<typename T, class C, typename L>
267 struct components_impl<T C::*, L>
268 : member_obj_ptr_components<T,C,L>
269 { };
270
271#else
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700272# define NDNBOOST_FT_variations NDNBOOST_FT_pointer
Jeff Thompsona28eed82013-08-22 16:21:10 -0700273
274 // This workaround removes the member pointer from the type to allow
275 // detection of member function pointers with BCC.
276 template<typename T, typename C, typename L>
277 struct components_impl<T C::*, L>
278 : detail::retagged_if
279 < detail::components_impl<typename ndnboost::remove_cv<T>::type *, L>
280 , pointer_tag, /* --> */ member_function_pointer_tag
281 , member_obj_ptr_components<T,C,L> >
282 { };
283
284 // BCC lets us test the cv-qualification of a function type by template
285 // partial specialization - so we use this bug feature to find out the
286 // member function's cv-qualification (unfortunately there are some
287 // invisible modifiers that impose some limitations on these types even if
288 // we remove the qualifiers, So we cannot exploit the same bug to make the
289 // library work for cv-qualified function types).
290 template<typename T> struct encode_cv
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700291 { typedef char (& type)[1]; NDNBOOST_STATIC_CONSTANT(std::size_t, value = 1); };
Jeff Thompsona28eed82013-08-22 16:21:10 -0700292 template<typename T> struct encode_cv<T const *>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700293 { typedef char (& type)[2]; NDNBOOST_STATIC_CONSTANT(std::size_t, value = 2); };
Jeff Thompsona28eed82013-08-22 16:21:10 -0700294 template<typename T> struct encode_cv<T volatile *>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700295 { typedef char (& type)[3]; NDNBOOST_STATIC_CONSTANT(std::size_t, value = 3); };
Jeff Thompsona28eed82013-08-22 16:21:10 -0700296 template<typename T> struct encode_cv<T const volatile *>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700297 { typedef char (& type)[4]; NDNBOOST_STATIC_CONSTANT(std::size_t, value = 4); };
Jeff Thompsona28eed82013-08-22 16:21:10 -0700298
299 // For member function pointers we have to use a function template (partial
300 // template specialization for a member pointer drops the cv qualification
301 // of the function type).
302 template<typename T, typename C>
303 typename encode_cv<T *>::type mfp_cv_tester(T C::*);
304
305 template<typename T> struct encode_mfp_cv
306 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700307 NDNBOOST_STATIC_CONSTANT(std::size_t, value =
Jeff Thompsona28eed82013-08-22 16:21:10 -0700308 sizeof(detail::mfp_cv_tester((T)0L)));
309 };
310
311 // Associate bits with the CV codes above.
312 template<std::size_t> struct cv_tag_mfp_impl;
313
314 template<typename T> struct cv_tag_mfp
315 : detail::cv_tag_mfp_impl
316 < ::ndnboost::function_types::detail::encode_mfp_cv<T>::value >
317 { };
318
319 template<> struct cv_tag_mfp_impl<1> : non_cv { };
320 template<> struct cv_tag_mfp_impl<2> : const_non_volatile { };
321 template<> struct cv_tag_mfp_impl<3> : volatile_non_const { };
322 template<> struct cv_tag_mfp_impl<4> : cv_qualified { };
323
324 // Metafunction to decode the cv code and apply it to a type.
325 // We add a pointer, because otherwise cv-qualifiers won't stick (another bug).
326 template<typename T, std::size_t CV> struct decode_cv;
327
328 template<typename T> struct decode_cv<T,1> : mpl::identity<T *> {};
329 template<typename T> struct decode_cv<T,2> : mpl::identity<T const *> {};
330 template<typename T> struct decode_cv<T,3> : mpl::identity<T volatile *> {};
331 template<typename T> struct decode_cv<T,4>
332 : mpl::identity<T const volatile *> {};
333
334 // The class type transformation comes after adding cv-qualifiers. We have
335 // wrap it to remove the pointer added in decode_cv_impl.
336 template<typename T, typename L> struct bcc_class_transform_impl;
337 template<typename T, typename L> struct bcc_class_transform_impl<T *, L>
338 : class_transform<T,L>
339 { };
340
341 template<typename T, typename D, typename L> struct bcc_class_transform
342 : bcc_class_transform_impl
343 < typename decode_cv
344 < T
345 , ::ndnboost::function_types::detail::encode_mfp_cv<D>::value
346 >::type
347 , L
348 >
349 { };
350
351 // After extracting the member pointee from the type the class type is still
352 // in the type (somewhere -- you won't see with RTTI, that is) and that type
353 // is flagged unusable and *not* identical to the nonmember function type.
354 // We can, however, decompose this type via components_impl but surprisingly
355 // a pointer to the const qualified class type pops up again as the first
356 // parameter type.
357 // We have to replace this type with the properly cv-qualified and
358 // transformed class type, integrate the cv qualification into the bits.
359 template<typename Base, typename MFP, typename OrigT, typename L>
360 struct mfp_components;
361
362
363 template<typename Base, typename T, typename C, typename OrigT, typename L>
364 struct mfp_components<Base,T C::*,OrigT,L>
365 {
366 private:
367 typedef typename mpl::front<typename Base::types>::type result_type;
368 typedef typename detail::bcc_class_transform<C,OrigT,L>::type class_type;
369
370 typedef mpl::vector2<result_type, class_type> result_and_class_type;
371
372 typedef typename
373 mpl::advance
374 < typename mpl::begin<typename Base::types>::type
375 , typename mpl::if_
376 < mpl::equal_to< typename detail::classifier<OrigT>::function_arity
377 , typename Base::function_arity >
378 , mpl::integral_c<int,2> , mpl::integral_c<int,1>
379 >::type
380 >::type
381 from;
382 typedef typename mpl::end<typename Base::types>::type to;
383
384 typedef mpl::iterator_range<from,to> param_types;
385
386 typedef mpl::joint_view< result_and_class_type, param_types> types_view;
387 public:
388
389 typedef typename
390 mpl::reverse_copy<types_view, mpl::front_inserter< mpl::vector0<> > >::type
391 types;
392
393 typedef typename
394 function_types::tag< Base, detail::cv_tag_mfp<OrigT> >::bits
395 bits;
396
397 typedef typename Base::mask mask;
398
399 typedef typename detail::classifier<OrigT>::function_arity function_arity;
400
401 typedef components_mpl_sequence_tag tag;
402 };
403
404 // Now put it all together: detect cv-qualification of function types and do
405 // the weird transformations above for member function pointers.
406 template<typename T, typename OrigT, typename L>
407 struct components_bcc
408 : mpl::if_
409 < detail::represents_impl< detail::components_impl<T,L>
410 , member_function_pointer_tag>
411 , detail::mfp_components<detail::components_impl<T,L>,T,OrigT,L>
412 , detail::components_impl<T,L>
413 >::type
414 { };
415
416#endif // end of BORLAND WORKAROUND
417
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700418#define NDNBOOST_FT_al_path ndnboost/function_types/detail/components_impl
Jeff Thompsona28eed82013-08-22 16:21:10 -0700419#include <ndnboost/function_types/detail/pp_loop.hpp>
420
421 } } // namespace function_types::detail
422
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700423 NDNBOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::components)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700424
425} // namespace ::boost
426
427#include <ndnboost/function_types/detail/components_as_mpl_sequence.hpp>
428#include <ndnboost/function_types/detail/retag_default_cc.hpp>
429
430#endif
431