Lumiera  0.pre.03
»edit your freedom«
trait.hpp
Go to the documentation of this file.
1 /*
2  TRAIT.hpp - type handling and type detection helpers
3 
4  Copyright (C)
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
49 #ifndef LIB_META_TRAIT_H
50 #define LIB_META_TRAIT_H
51 
52 
53 #include "lib/meta/util.hpp"
55 
56 #include <type_traits>
57 
58 
59 //Forward declarations for the Unwrap helper....
60 namespace boost{
61  template<class X> class reference_wrapper;
62 }
63 namespace std {
64  template<class X> class reference_wrapper;
65  template<class X> class shared_ptr;
66  template<class X, class D> class unique_ptr;
67  template<class C, class T> class basic_filebuf;
68  template<class C> class char_traits;
69 }
70 namespace lib{
71  template<class X, class B> class P;
72 
73  namespace hash {
74  class LuidH;
75  }
76  namespace time {
77  class TimeValue;
78  class Duration;
79 }}
80 namespace steam {
81 namespace mobject{
82  template<class X, class B> class Placement;
83 }}
84 
85 
86 namespace lib {
87 namespace meta {
88 
89  using std::remove_cv_t;
90  using std::remove_pointer_t;
91  using std::remove_reference_t;
92  using std::conditional_t;
93  using std::is_reference_v;
94  using std::is_lvalue_reference_v;
95  using std::is_rvalue_reference_v;
96  using std::is_pointer;
97  using std::is_base_of;
98  using std::is_convertible;
99  using std::is_constructible;
100  using std::is_floating_point;
101  using std::is_arithmetic;
102  using std::is_unsigned;
103  using std::is_signed;
104  using std::is_class;
105  using std::is_same;
106  using std::__not_;
107  using std::__and_;
108  using std::__or_;
109 
110  template<typename T>
111  static constexpr bool isConst_v = std::is_const_v<remove_reference_t<T>>;
112  template<typename T>
113  static constexpr bool isLRef_v = std::is_lvalue_reference_v<T>;
114  template<typename T>
115  static constexpr bool isRRef_v = std::is_rvalue_reference_v<T>;
116  template<typename T>
117  static constexpr bool isRef_v = std::is_reference_v<T>;
118 
119 
128  template<typename X>
129  struct Unwrap
130  : std::false_type
131  {
132  using Type = X;
133 
134  static X&
135  extract (X const& x)
136  {
137  return const_cast<X&> (x);
138  }
139  };
140 
141  template<>
142  struct Unwrap<void>
143  : std::false_type
144  {
145  using Type = void;
146  };
147 
148  template<typename X>
149  struct Unwrap<X*>
150  : std::true_type
151  {
152  using Type = remove_cv_t<X>;
153 
154  static Type&
155  extract (const X* ptr)
156  {
157  ASSERT (ptr);
158  return const_cast<Type&> (*ptr);
159  }
160  };
161 
162  template<typename X>
163  struct Unwrap<boost::reference_wrapper<X>>
164  : std::true_type
165  {
166  using Type = X;
167 
168  static X&
169  extract (boost::reference_wrapper<X> wrapped)
170  {
171  return wrapped;
172  }
173  };
174 
175  template<typename X>
176  struct Unwrap<std::reference_wrapper<X>>
177  : std::true_type
178  {
179  using Type = X;
180 
181  static X&
182  extract (std::reference_wrapper<X> wrapped)
183  {
184  return wrapped;
185  }
186  };
187 
188  template<typename X, class D>
189  struct Unwrap<std::unique_ptr<X,D>>
190  : std::true_type
191  {
192  using Type = X;
193 
194  static X&
195  extract (std::unique_ptr<X,D> const& ptr)
196  {
197  ASSERT (ptr);
198  return *ptr;
199  }
200  };
201 
202  template<typename X>
203  struct Unwrap<std::shared_ptr<X>>
204  : std::true_type
205  {
206  using Type = X;
207 
208  static X&
209  extract (std::shared_ptr<X> const& ptr)
210  {
211  ASSERT (ptr);
212  return *ptr;
213  }
214  };
215 
216  template<typename X, class B>
217  struct Unwrap<P<X, B>>
218  : std::true_type
219  {
220  using Type = X;
221 
222  static X&
223  extract (P<X,B> ptr)
224  {
225  ASSERT (ptr);
226  return *ptr;
227  }
228  };
229 
230 
238  template<typename X>
239  typename Unwrap<X>::Type&
240  unwrap (X const& wrapped)
241  {
242  return Unwrap<X>::extract(wrapped);
243  }
244 
245 
246 
247 
249  template<typename X>
250  struct Strip
251  {
252  using TypeUnconst = conditional_t<is_reference_v<X>
253  , conditional_t<is_rvalue_reference_v<X>
254  , remove_cv_t<remove_reference_t<X>> &&
255  , remove_cv_t<remove_reference_t<X>> & >
256  , remove_cv_t<X>>;
257  using TypeReferred = remove_reference_t<TypeUnconst>;
258  using TypePointee = remove_pointer_t<TypeReferred>;
259  using TypePlain = remove_cv_t<TypePointee>;
260 
261  using Type = typename Unwrap<TypePlain>::Type;
262  };
263 
264 
265 
266 
274  template<typename TY>
275  struct RefTraits
276  {
277  typedef TY Value;
278  typedef TY* Pointer;
279  typedef TY& Reference;
280  };
281 
282  template<typename TY>
283  struct RefTraits<TY *>
284  {
285  typedef TY* Value;
286  typedef TY** Pointer;
287  typedef TY*& Reference;
288  };
289 
290  template<typename TY>
291  struct RefTraits<TY &>
292  {
293  typedef TY Value;
294  typedef TY* Pointer;
295  typedef TY& Reference;
296  };
297 
298  template<typename TY>
299  struct RefTraits<TY &&>
300  {
301  typedef TY Value;
302  typedef TY* Pointer;
303  typedef TY& Reference;
304  };
305 
306 
307 
308 
309 
310 
311 
312  /* ==== Traits ==== */
313 
315  template<typename T, typename U>
317  : is_same <typename Strip<T>::TypeReferred
318  ,typename Strip<U>::TypeReferred>
319  { };
320 
322  template<typename S, typename I>
323  struct is_Subclass
324  : __or_< __and_< is_class<I>
325  , is_class<S>
326  , is_base_of<I,S>
327  >
328  , is_same<I,S>
329  >
330  { };
331 
333  template<typename S, typename I>
335  : is_Subclass <typename Strip<S>::TypeReferred
336  ,typename Strip<I>::TypeReferred>
337  { };
338 
340  template<typename S, typename G>
341  struct can_StandIn
342  : std::is_convertible<typename RefTraits<S>::Reference
343  ,typename RefTraits<G>::Reference
344  >
345  { };
346 
348  template<typename X>
350  : __or_< is_basically<X, std::string>
351  , is_basically<X, std::string_view>
352  , is_convertible<X, const char*>
353  >
354  { };
355 
372  template<typename X>
374  : __or_< is_arithmetic<X>
375  , is_StringLike<X>
376  >
377  { };
378 
379  template<typename X>
381  : __and_<can_lexical2string<X>
382  ,__not_<can_convertToString<X>>
383  >
384  { };
385 
386  // need to exclude files and input streams from automatic string conversion
387  template<typename X>
389  : is_same<X, std::basic_filebuf<char, std::char_traits<char> > >
390  { };
391 
393  template<typename X>
395  : __and_<is_class<typename Strip<X>::TypePlain>
396  ,__not_<is_pointer<X>>
397  ,__not_<can_lexical2string<X>>
398  ,__not_<is_StreamSource<X>>
399  >
400  { };
401 
402 
404  template<typename X>
406  : std::false_type
407  { };
408 
409  template<typename T>
411  : std::true_type
412  { };
413 
414  template <typename T, typename D>
415  struct is_smart_ptr<std::unique_ptr<T,D>>
416  : std::true_type
417  { };
418 
419 
420 
421 
422 
423 
424  template<typename NUM>
425  struct is_nonFloat
426  : __and_<is_arithmetic<NUM>
427  ,__not_<is_floating_point<NUM>>
428  >
429  { };
430 
447  template<typename SRC, typename TAR>
449  : __or_<__and_<is_unsigned<SRC>, is_signed<TAR>>
450  ,__and_<is_signed<SRC>, is_unsigned<TAR>>
451  ,__and_<is_nonFloat<SRC>, is_floating_point<TAR>>
452  ,__and_<is_floating_point<SRC>, is_nonFloat<TAR>>
453  ,__not_<is_constructible<TAR, SRC>>
454  >
455  { };
456 
457  template<typename TAR>
459  : __or_<is_arithmetic<TAR>
460  ,is_floating_point<TAR>
461  >
462  { };
463 
464 #define TRAIT_IS_NARROWING(_SRC_, _TAR_) \
465  template<> \
466  struct is_narrowingInit<_SRC_, _TAR_> \
467  : std::true_type \
468  { };
469 
470  TRAIT_IS_NARROWING (int64_t, int32_t)
471  TRAIT_IS_NARROWING (int64_t, int16_t)
472  TRAIT_IS_NARROWING (int64_t, int8_t)
473  TRAIT_IS_NARROWING (int64_t, char)
474  TRAIT_IS_NARROWING (int32_t, int16_t)
475  TRAIT_IS_NARROWING (int32_t, int8_t)
476  TRAIT_IS_NARROWING (int32_t, char)
477  TRAIT_IS_NARROWING (int16_t, int8_t)
478  TRAIT_IS_NARROWING (int16_t, short)
479  TRAIT_IS_NARROWING (int16_t, char)
480 
481  TRAIT_IS_NARROWING (uint64_t, uint32_t)
482  TRAIT_IS_NARROWING (uint64_t, uint16_t)
483  TRAIT_IS_NARROWING (uint64_t, uint8_t)
484  TRAIT_IS_NARROWING (uint32_t, uint16_t)
485  TRAIT_IS_NARROWING (uint32_t, uint8_t)
486  TRAIT_IS_NARROWING (uint16_t, uint8_t)
487  TRAIT_IS_NARROWING (uint16_t, ushort)
488 
489  TRAIT_IS_NARROWING (double, float)
490 
491  TRAIT_IS_NARROWING (double, lib::time::TimeValue)
492  TRAIT_IS_NARROWING (double, lib::time::Duration)
493 
494 #undef TRAIT_IS_NARROWING
495 
496 
497 
498 
499 
500 
501  /* ====== generic iteration support ====== */
502 
509  template<typename T>
511  {
512  using Type = typename Strip<T>::Type;
513 
514  META_DETECT_NESTED(value_type);
517 
518  public:
519  enum{ value = std::is_constructible<bool, Type>::value
520  and HasNested_value_type<Type>::value
521  and HasOperator_deref<Type>::value
522  and HasOperator_inc<Type>::value
523  };
524  };
525 
526 
527 
533  template<typename T>
535  {
536  using Type = typename Strip<T>::Type;
537 
538  META_DETECT_FUNCTION_ARGLESS(checkPoint);
541 
542  public:
543  enum{ value = HasArglessFun_checkPoint<Type>::value
544  and HasArglessFun_iterNext<Type>::value
545  and HasArglessFun_yield<Type>::value
546  };
547  };
548 
549 
550 
554  template<typename T>
556  {
557  using Type = typename Strip<T>::Type;
558 
559  struct is_iterable
560  {
561  META_DETECT_NESTED(iterator);
562  META_DETECT_FUNCTION(typename X::iterator, begin,(void));
563  META_DETECT_FUNCTION(typename X::iterator, end ,(void));
564 
565  enum { value = HasNested_iterator<Type>::value
566  and HasFunSig_begin<Type>::value
567  and HasFunSig_end<Type>::value
568  };
569  };
570 
572  {
573  META_DETECT_NESTED(iterator);
574  META_DETECT_FUNCTION(typename X::iterator, begin,(void) noexcept);
575  META_DETECT_FUNCTION(typename X::iterator, end ,(void) noexcept);
576 
577  enum { value = HasNested_iterator<Type>::value
578  and HasFunSig_begin<Type>::value
579  and HasFunSig_end<Type>::value
580  };
581  };
582 
584  {
585  META_DETECT_NESTED(const_iterator);
586  META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const);
587  META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const);
588 
589  enum { value = HasNested_const_iterator<Type>::value
590  and HasFunSig_begin<Type>::value
591  and HasFunSig_end<Type>::value
592  };
593  };
594 
596  {
597  META_DETECT_NESTED(const_iterator);
598  META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const noexcept);
599  META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const noexcept);
600 
601  enum { value = HasNested_const_iterator<Type>::value
602  and HasFunSig_begin<Type>::value
603  and HasFunSig_end<Type>::value
604  };
605  };
606 
607 
608  public:
609  enum { value = is_iterable::value
610  or is_const_iterable::value
611  or is_noexcept_iterable::value
612  or is_const_noexcept_iterable::value
613  };
614  };
615 
616 
618  template<typename T>
620  {
621  using Type = typename Strip<T>::Type;
622 
624  {
625  META_DETECT_NESTED(reverse_iterator);
626  META_DETECT_FUNCTION(typename X::reverse_iterator, rbegin,(void));
627  META_DETECT_FUNCTION(typename X::reverse_iterator, rend ,(void));
628 
629  enum { value = HasNested_reverse_iterator<Type>::value
630  and HasFunSig_rbegin<Type>::value
631  and HasFunSig_rend<Type>::value
632  };
633  };
634 
636  {
637  META_DETECT_NESTED(reverse_iterator);
638  META_DETECT_FUNCTION(typename X::reverse_iterator, rbegin,(void) noexcept);
639  META_DETECT_FUNCTION(typename X::reverse_iterator, rend ,(void) noexcept);
640 
641  enum { value = HasNested_reverse_iterator<Type>::value
642  and HasFunSig_rbegin<Type>::value
643  and HasFunSig_rend<Type>::value
644  };
645  };
646 
648  {
649  META_DETECT_NESTED(const_reverse_iterator);
650  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rbegin,(void) const);
651  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rend ,(void) const);
652 
653  enum { value = HasNested_const_reverse_iterator<Type>::value
654  and HasFunSig_rbegin<Type>::value
655  and HasFunSig_rend<Type>::value
656  };
657  };
658 
660  {
661  META_DETECT_NESTED(const_reverse_iterator);
662  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rbegin,(void) const noexcept);
663  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rend ,(void) const noexcept);
664 
665  enum { value = HasNested_const_reverse_iterator<Type>::value
666  and HasFunSig_rbegin<Type>::value
667  and HasFunSig_rend<Type>::value
668  };
669  };
670 
671 
672  public:
673  enum { value = is_backIterable::value
674  or is_const_backIterable::value
675  or is_noexcept_backIterable::value
676  or is_const_noexcept_backIterable::value
677  };
678  };
679 
680 
681 
682 }} // namespace lib::meta
683 #endif
A refcounting Handle to an MObject of type MO, used to constrain or explicitly specify the location w...
Definition: trait.hpp:82
#define META_DETECT_OPERATOR_INC()
Detector for a prefix increment operator.
Definition: trait.hpp:60
Trait template to detect a type usable with the STL for-each loop.
Definition: trait.hpp:555
Trait template to detect a type also supporting STL-style backwards iteration.
Definition: trait.hpp:619
Simple and lightweight helpers for metaprogramming and type detection.
STL namespace.
Trait template to detect a type exposing a »state core« API.
Definition: trait.hpp:534
types able to be lexically converted to string representation
Definition: trait.hpp:373
Helper for type analysis and convenience accessors: attempts to extract a base type from various wrap...
Definition: trait.hpp:129
compare for unadorned base type, disregarding const and references
Definition: trait.hpp:334
verify the first (special) type can stand-in for the second
Definition: trait.hpp:341
#define META_DETECT_FUNCTION(_RET_TYPE_, _FUN_NAME_, _ARGS_)
Detector for a specific member function.
Steam-Layer implementation namespace root.
Implementation namespace for support and library code.
#define META_DETECT_FUNCTION_ARGLESS(_FUN_)
Detector for an argument-less member function with the given name.
when to use custom string conversions for output streams
Definition: trait.hpp:394
Helper for type analysis: tries to strip all kinds of type adornments.
Definition: trait.hpp:250
Trait template to detect a type usable immediately as "Lumiera Forward Iterator" in a specialised for...
Definition: trait.hpp:510
#define META_DETECT_OPERATOR_DEREF()
Detector for a dereferentiation operator.
compare unadorned types, disregarding const and references
Definition: trait.hpp:316
Hash implementation based on a lumiera unique object id (LUID) When invoking the default ctor...
temporary workaround for GCC [Bug-63723], necessary until CGG-5
Definition: trait.hpp:448
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:468
Unwrap< X >::Type & unwrap(X const &wrapped)
convenience shortcut: unwrapping free function.
Definition: trait.hpp:240
#define META_DETECT_NESTED(_TYPE_)
Detector for a nested type.
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:71
detect smart pointers
Definition: trait.hpp:405
Type definition helper for pointer and reference types.
Definition: trait.hpp:275
detect various flavours of string / text data
Definition: trait.hpp:349
verify compliance to an interface by subtype check
Definition: trait.hpp:323
basic constant internal time value.
Definition: timevalue.hpp:133
Metaprogramming helpers to check for specific properties of a type in question.