FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
meta_util_impl.h
1 /**********************************************************\
2 Original Author: Georg Fritzsche
3 
4 Created: December 22, 2009
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2009 Georg Fritzsche, Firebreath development team
13 \**********************************************************/
14 
15 #pragma once
16 #ifndef H_META_UTIL_IMPL_22122009
17 #define H_META_UTIL_IMPL_22122009
18 
19 #include <utility>
20 #include <boost/utility/enable_if.hpp>
21 #include <boost/mpl/equal_to.hpp>
22 #include <boost/mpl/vector.hpp>
23 #include <boost/mpl/contains.hpp>
24 #include <boost/mpl/and.hpp>
25 #include <boost/type_traits.hpp>
26 #include <boost/variant/variant_fwd.hpp>
27 
28 namespace FB { namespace meta { namespace detail
29 {
30  class yes { yes() : c(0) { (void)c; }; char c; };
31  class no { yes y[2]; };
32 
33 #define FB_HAS_TYPE(Type_, Name_) \
34  template<class T> \
35  struct Name_ { \
36  template<class U> static yes test(typename U::Type_ const*); \
37  template<class U> static no test(...); \
38  static const bool value = (sizeof(test<T>(0)) == sizeof(yes)); \
39  typedef boost::mpl::bool_<value> type; \
40  }
41 
42  FB_HAS_TYPE(iterator, has_type_iterator);
43  FB_HAS_TYPE(const_iterator, has_type_const_iterator);
44  FB_HAS_TYPE(key_type, has_type_key_type);
45  FB_HAS_TYPE(value_type, has_type_value_type);
46  FB_HAS_TYPE(mapped_type, has_type_mapped_type);
47 // FB_HAS_TYPE(reference, has_type_reference);
48 // FB_HAS_TYPE(const_reference, has_type_const_reference);
49  FB_HAS_TYPE(pointer, has_type_pointer);
50  FB_HAS_TYPE(difference_type, has_type_difference_type);
51  FB_HAS_TYPE(size_type, has_type_size_type);
52 
53 #undef FB_HAS_TYPE
54 
55  template<class C>
56  class is_container_impl
57  {
58  private:
59  struct mixin
60  {
61  void begin() const;
62  void end() const;
63  void size() const;
64  void max_size() const;
65  void empty() const;
66  void swap(char);
67  };
68 
69  struct derivate : public C, public mixin {};
70  template<class U, U t> struct helper {};
71 
72  template<class U> static no test_begin(helper<void (mixin::*)() const, &U::begin>*);
73  template<class U> static yes test_begin(...);
74  template<class U> static no test_end(helper<void (mixin::*)() const, &U::end>*);
75  template<class U> static yes test_end(...);
76  template<class U> static no test_size(helper<void (mixin::*)() const, &U::size>*);
77  template<class U> static yes test_size(...);
78  template<class U> static no test_max_size(helper<void (mixin::*)() const, &U::max_size>*);
79  template<class U> static yes test_max_size(...);
80  template<class U> static no test_empty(helper<void (mixin::*)() const, &U::empty>*);
81  template<class U> static yes test_empty(...);
82  template<class U> static no test_swap(helper<void (mixin::*)(char), &U::swap>*);
83  template<class U> static yes test_swap(...);
84 
85  public:
86  static const bool has_memfun_begin = (sizeof(yes) == sizeof(test_begin <derivate>(0)));
87  static const bool has_memfun_end = (sizeof(yes) == sizeof(test_end <derivate>(0)));
88  static const bool has_memfun_size = (sizeof(yes) == sizeof(test_size <derivate>(0)));
89  static const bool has_memfun_max_size = (sizeof(yes) == sizeof(test_max_size<derivate>(0)));
90  static const bool has_memfun_empty = (sizeof(yes) == sizeof(test_empty <derivate>(0)));
91  static const bool has_memfun_swap = (sizeof(yes) == sizeof(test_swap <derivate>(0)));
92 
93  static const bool value =
94  has_type_iterator<C>::value
95  && has_type_const_iterator<C>::value
96  && has_type_value_type<C>::value
97 // && has_type_reference<C>::value
98 // && has_type_const_reference<C>::value
99  && has_type_pointer<C>::value
100  && has_type_difference_type<C>::value
101  && has_type_size_type<C>::value
102  && has_memfun_begin
103  && has_memfun_size
104  && has_memfun_max_size
105  && has_memfun_empty
106  && has_memfun_swap;
107  typedef boost::mpl::bool_<value> type;
108  };
109 
110  template<class C>
111  class is_assoc_impl
112  {
113  struct mixin
114  {
115  void erase(char);
116  void erase(char, char);
117  void clear();
118  void find(char) const;
119  void count(char) const;
120  void equal_range(char) const;
121  };
122 
123  struct derivate : public C, public mixin {};
124  template<class U, U t> struct helper {};
125 
126  template<class U> static no test_erase_1(helper<void (mixin::*)(char), &U::erase>*);
127  template<class U> static yes test_erase_1(...);
128  template<class U> static no test_erase_2(helper<void (mixin::*)(char, char), &U::erase>*);
129  template<class U> static yes test_erase_2(...);
130  template<class U> static no test_clear(helper<void (mixin::*)(), &U::clear>*);
131  template<class U> static yes test_clear(...);
132  template<class U> static no test_find(helper<void (mixin::*)(char) const, &U::find>*);
133  template<class U> static yes test_find(...);
134  template<class U> static no test_count(helper<void (mixin::*)(char) const, &U::count>*);
135  template<class U> static yes test_count(...);
136  template<class U> static no test_equal_range(helper<void (mixin::*)(char) const, &U::equal_range>*);
137  template<class U> static yes test_equal_range(...);
138 
139  public:
140  static const bool has_memfun_erase_1 = (sizeof(yes) == sizeof(test_erase_1 <derivate>(0)));
141  static const bool has_memfun_erase_2 = (sizeof(yes) == sizeof(test_erase_2 <derivate>(0)));
142  static const bool has_memfun_clear = (sizeof(yes) == sizeof(test_clear <derivate>(0)));
143  static const bool has_memfun_find = (sizeof(yes) == sizeof(test_find <derivate>(0)));
144  static const bool has_memfun_count = (sizeof(yes) == sizeof(test_count <derivate>(0)));
145  static const bool has_memfun_equal_range = (sizeof(yes) == sizeof(test_equal_range<derivate>(0)));
146 
147  static const bool value =
148  has_type_key_type<C>::value
149  && has_memfun_erase_1
150  && has_memfun_erase_2
151  && has_memfun_clear
152  && has_memfun_find
153  && has_memfun_count
154  && has_memfun_equal_range;
155  typedef boost::mpl::bool_<value> type;
156  };
157 
158  template<bool has_mapped_type, class T>
159  struct check_pair_assoc_value_type
160  {
161  typedef typename T::key_type Key;
162  typedef typename T::mapped_type Mapped;
163  typedef typename T::value_type Value;
164  typedef std::pair<const Key, Mapped> Pair;
165 
166  static const bool value = boost::is_same<Value, Pair>::value;
167  };
168 
169  template<class T>
170  struct check_pair_assoc_value_type<false, T>
171  {
172  static const bool value = false;
173  };
174 
175  template<class T>
176  class is_pair_assoc_impl
177  {
178 
179  public:
180  static const bool has_mapped_type = has_type_mapped_type<T>::value;
181  static const bool value_type_is_pair =
182  check_pair_assoc_value_type<has_mapped_type, T>::value;
183 
184  static const bool value = value_type_is_pair;
185  typedef boost::mpl::bool_<value> type;
186  };
187 
188  typedef boost::mpl::vector
189  <
190  std::string,
191  std::wstring
192  > pseudo_container_types;
193 
194  template<typename T>
195  struct plain_type {
196  typedef typename boost::remove_const<typename boost::remove_reference<T>::type>::type type;
197  };
198 
199  template<class T>
200  struct is_pseudo_container
201  : boost::mpl::contains<pseudo_container_types, typename plain_type<T>::type>::type
202  {};
203 
205  // is_container
206 
207  template<bool isClass, class T>
208  struct is_container_helper
209  : boost::mpl::and_<
210  boost::mpl::not_< is_pseudo_container<T> >,
211  typename is_container_impl<T>::type >::type
212  {};
213 
214  template<class T>
215  struct is_container_helper<false, T>
216  : boost::mpl::false_
217  {};
218 
219  template<class T>
220  struct is_container
221  : is_container_helper<boost::is_class<T>::value, T>
222  {};
223 
225  // is_assoc_container
226 
227  template<bool isClass, class T>
228  struct is_assoc_container_helper
229  : boost::mpl::and_<
230  typename is_assoc_impl<T>::type,
231  is_container<T> >::type
232  {};
233 
234  template<class T>
235  struct is_assoc_container_helper<false, T>
236  : boost::mpl::false_
237  {};
238 
239  template<class T>
240  struct is_assoc_container
241  : is_assoc_container_helper<boost::is_class<T>::value, T>
242  {};
243 
245  // is_pair_assoc_container
246 
247  template<bool isClass, class T>
248  struct is_pair_assoc_container_helper
249  : boost::mpl::and_<
250  typename is_pair_assoc_impl<T>::type,
251  is_assoc_container<T> >::type
252  {};
253 
254  template<class T>
255  struct is_pair_assoc_container_helper<false, T>
256  : boost::mpl::false_
257  {};
258 
259  template<class T>
260  struct is_pair_assoc_container
261  : is_pair_assoc_container_helper<boost::is_class<T>::value, T>
262  {};
263 
265  // is_non_assoc_container
266 
267  template<bool isClass, class T>
268  struct is_non_assoc_container_helper
269  : boost::mpl::and_<
270  boost::mpl::not_<is_assoc_container<T> >,
271  is_container<T> >::type
272  {};
273 
274  template<class T>
275  struct is_non_assoc_container_helper<false, T>
276  : boost::mpl::false_
277  {};
278 
279  template<class T>
280  struct is_non_assoc_container
281  : is_non_assoc_container_helper<boost::is_class<T>::value, T>
282  {};
283 
285  // is number - we consider bool as a non-number
286 
287  template<class T>
288  struct is_number
289  : boost::mpl::and_<
290  boost::is_arithmetic<T>,
291  boost::mpl::not_<
292  boost::is_same<T, bool>
293  >
294  >
295  {};
296 
298  // enable_if helpers:
299  // T - the type to compare
300  // R - the return type
301 
302  template<class T, typename R>
303  struct enable_for_numbers_impl
304  : boost::enable_if<is_number<T>, R>
305  {};
306 
307  template<class T, typename R>
308  struct disable_for_numbers_impl
309  : boost::disable_if<is_number<T>, R>
310  {};
311 
312  template<class T, typename R>
313  struct enable_for_containers_impl
314  : boost::enable_if<is_container<T>, R>
315  {};
316 
317  template<class T, typename R>
318  struct disable_for_containers_impl
319  : boost::disable_if<is_container<T>, R>
320  {};
321 
322  template<class T, typename R>
323  struct enable_for_containers_and_numbers_impl
324  : boost::enable_if<
325  boost::mpl::or_<
326  is_container<T>,
327  is_number<T>
328  >,
329  R
330  >
331  {};
332 
333  template<class T, typename R>
334  struct disable_for_containers_and_numbers_impl
335  : boost::disable_if<
336  boost::mpl::or_<
337  is_container<T>,
338  is_number<T>
339  >,
340  R
341  >
342  {};
343 
344  template<class T, typename R>
345  struct enable_for_assoc_containers_impl
346  : boost::enable_if<is_assoc_container<T>, R>
347  {};
348 
349  template<class T, typename R>
350  struct disable_for_assoc_containers_impl
351  : boost::disable_if<is_assoc_container<T>, R>
352  {};
353 
354  template<class T, typename R>
355  struct enable_for_pair_assoc_containers_impl
356  : boost::enable_if<is_pair_assoc_container<T>, R>
357  {};
358 
359  template<class T, typename R>
360  struct disable_for_pair_assoc_containers_impl
361  : boost::disable_if<is_pair_assoc_container<T>, R>
362  {};
363 
364  template<class T, typename R>
365  struct enable_for_non_assoc_containers_impl
366  : boost::enable_if<is_non_assoc_container<T>, R>
367  {};
368 
369  template<class T, typename R>
370  struct disable_for_non_assoc_containers_impl
371  : boost::disable_if<is_non_assoc_container<T>, R>
372  {};
373 
374 }; }; };
375 
376 #endif
377