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) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
58 #ifndef LIB_META_TRAIT_H
59 #define LIB_META_TRAIT_H
60 
61 
62 #include "lib/meta/util.hpp"
64 
65 #include <type_traits>
66 
67 
68 //Forward declarations for the Unwrap helper....
69 namespace boost{
70  template<class X> class reference_wrapper;
71 }
72 namespace std {
73  template<class X> class reference_wrapper;
74  template<class X> class shared_ptr;
75  template<class X, class D> class unique_ptr;
76  template<class C, class T> class basic_filebuf;
77  template<class C> class char_traits;
78 }
79 namespace lib{
80  template<class X, class B> class P;
81 
82  namespace hash {
83  class LuidH;
84  }
85  namespace time {
86  class TimeValue;
87  class Duration;
88 }}
89 namespace steam {
90 namespace mobject{
91  template<class X, class B> class Placement;
92 }}
93 
94 
95 namespace lib {
96 namespace meta {
97 
98  using std::remove_cv;
99  using std::remove_cv_t;
100  using std::remove_pointer;
101  using std::remove_pointer_t;
102  using std::remove_reference;
103  using std::remove_reference_t;
104  using std::is_pointer;
105  using std::is_base_of;
106  using std::is_convertible;
107  using std::is_constructible;
108  using std::is_floating_point;
109  using std::is_arithmetic;
110  using std::is_unsigned;
111  using std::is_signed;
112  using std::is_class;
113  using std::is_same;
114  using std::__not_;
115  using std::__and_;
116  using std::__or_;
117 
118 
127  template<typename X>
128  struct Unwrap
129  : std::false_type
130  {
131  using Type = X;
132 
133  static X&
134  extract (X const& x)
135  {
136  return const_cast<X&> (x);
137  }
138  };
139 
140  template<>
141  struct Unwrap<void>
142  : std::false_type
143  {
144  using Type = void;
145  };
146 
147  template<typename X>
148  struct Unwrap<X*>
149  : std::true_type
150  {
151  using Type = remove_cv_t<X>;
152 
153  static Type&
154  extract (const X* ptr)
155  {
156  ASSERT (ptr);
157  return const_cast<Type&> (*ptr);
158  }
159  };
160 
161  template<typename X>
162  struct Unwrap<boost::reference_wrapper<X>>
163  : std::true_type
164  {
165  using Type = X;
166 
167  static X&
168  extract (boost::reference_wrapper<X> wrapped)
169  {
170  return wrapped;
171  }
172  };
173 
174  template<typename X>
175  struct Unwrap<std::reference_wrapper<X>>
176  : std::true_type
177  {
178  using Type = X;
179 
180  static X&
181  extract (std::reference_wrapper<X> wrapped)
182  {
183  return wrapped;
184  }
185  };
186 
187  template<typename X, class D>
188  struct Unwrap<std::unique_ptr<X,D>>
189  : std::true_type
190  {
191  using Type = X;
192 
193  static X&
194  extract (std::unique_ptr<X,D> const& ptr)
195  {
196  ASSERT (ptr);
197  return *ptr;
198  }
199  };
200 
201  template<typename X>
202  struct Unwrap<std::shared_ptr<X>>
203  : std::true_type
204  {
205  using Type = X;
206 
207  static X&
208  extract (std::shared_ptr<X> const& ptr)
209  {
210  ASSERT (ptr);
211  return *ptr;
212  }
213  };
214 
215  template<typename X, class B>
216  struct Unwrap<P<X, B>>
217  : std::true_type
218  {
219  using Type = X;
220 
221  static X&
222  extract (P<X,B> ptr)
223  {
224  ASSERT (ptr);
225  return *ptr;
226  }
227  };
228 
229 
237  template<typename X>
238  typename Unwrap<X>::Type&
239  unwrap (X const& wrapped)
240  {
241  return Unwrap<X>::extract(wrapped);
242  }
243 
244 
245 
246 
248  template<typename X>
249  struct Strip
250  {
251  using TypeUnconst = remove_cv_t<X>;
252  using TypeReferred = remove_reference_t<TypeUnconst>;
253  using TypePointee = remove_pointer_t<TypeReferred>;
254  using TypePlain = remove_cv_t<TypePointee>;
255 
256  using Type = typename Unwrap<TypePlain>::Type;
257  };
258 
259 
260 
261 
269  template<typename TY>
270  struct RefTraits
271  {
272  typedef TY Value;
273  typedef TY* Pointer;
274  typedef TY& Reference;
275  };
276 
277  template<typename TY>
278  struct RefTraits<TY *>
279  {
280  typedef TY* Value;
281  typedef TY** Pointer;
282  typedef TY*& Reference;
283  };
284 
285  template<typename TY>
286  struct RefTraits<TY &>
287  {
288  typedef TY Value;
289  typedef TY* Pointer;
290  typedef TY& Reference;
291  };
292 
293  template<typename TY>
294  struct RefTraits<TY &&>
295  {
296  typedef TY Value;
297  typedef TY* Pointer;
298  typedef TY& Reference;
299  };
300 
301 
302 
303 
304 
305 
306 
307  /* ==== Traits ==== */
308 
310  template<typename T, typename U>
312  : is_same <typename Strip<T>::TypeReferred
313  ,typename Strip<U>::TypeReferred>
314  { };
315 
317  template<typename S, typename I>
318  struct is_Subclass
319  : __or_< __and_< is_class<I>
320  , is_class<S>
321  , is_base_of<I,S>
322  >
323  , is_same<I,S>
324  >
325  { };
326 
328  template<typename S, typename I>
330  : is_Subclass <typename Strip<S>::TypeReferred
331  ,typename Strip<I>::TypeReferred>
332  { };
333 
335  template<typename S, typename G>
336  struct can_StandIn
337  : std::is_convertible<typename RefTraits<S>::Reference
338  ,typename RefTraits<G>::Reference
339  >
340  { };
341 
343  template<typename X>
345  : __or_< is_basically<X, std::string>
346  , is_basically<X, std::string_view>
347  , is_convertible<X, const char*>
348  >
349  { };
350 
367  template<typename X>
369  : __or_< is_arithmetic<X>
370  , is_StringLike<X>
371  >
372  { };
373 
374  template<typename X>
376  : __and_<can_lexical2string<X>
377  ,__not_<can_convertToString<X>>
378  >
379  { };
380 
381  // need to exclude files and input streams from automatic string conversion
382  template<typename X>
384  : is_same<X, std::basic_filebuf<char, std::char_traits<char> > >
385  { };
386 
388  template<typename X>
390  : __and_<is_class<typename Strip<X>::TypePlain>
391  ,__not_<is_pointer<X>>
392  ,__not_<can_lexical2string<X>>
393  ,__not_<is_StreamSource<X>>
394  >
395  { };
396 
397 
399  template<typename X>
401  : std::false_type
402  { };
403 
404  template<typename T>
406  : std::true_type
407  { };
408 
409  template <typename T, typename D>
410  struct is_smart_ptr<std::unique_ptr<T,D>>
411  : std::true_type
412  { };
413 
414 
415 
416 
417 
418 
419  template<typename NUM>
420  struct is_nonFloat
421  : __and_<is_arithmetic<NUM>
422  ,__not_<is_floating_point<NUM>>
423  >
424  { };
425 
442  template<typename SRC, typename TAR>
444  : __or_<__and_<is_unsigned<SRC>, is_signed<TAR>>
445  ,__and_<is_signed<SRC>, is_unsigned<TAR>>
446  ,__and_<is_nonFloat<SRC>, is_floating_point<TAR>>
447  ,__and_<is_floating_point<SRC>, is_nonFloat<TAR>>
448  ,__not_<is_constructible<TAR, SRC>>
449  >
450  { };
451 
452  template<typename TAR>
454  : __or_<is_arithmetic<TAR>
455  ,is_floating_point<TAR>
456  >
457  { };
458 
459 #define TRAIT_IS_NARROWING(_SRC_, _TAR_) \
460  template<> \
461  struct is_narrowingInit<_SRC_, _TAR_> \
462  : std::true_type \
463  { };
464 
465  TRAIT_IS_NARROWING (int64_t, int32_t)
466  TRAIT_IS_NARROWING (int64_t, int16_t)
467  TRAIT_IS_NARROWING (int64_t, int8_t)
468  TRAIT_IS_NARROWING (int64_t, char)
469  TRAIT_IS_NARROWING (int32_t, int16_t)
470  TRAIT_IS_NARROWING (int32_t, int8_t)
471  TRAIT_IS_NARROWING (int32_t, char)
472  TRAIT_IS_NARROWING (int16_t, int8_t)
473  TRAIT_IS_NARROWING (int16_t, short)
474  TRAIT_IS_NARROWING (int16_t, char)
475 
476  TRAIT_IS_NARROWING (uint64_t, uint32_t)
477  TRAIT_IS_NARROWING (uint64_t, uint16_t)
478  TRAIT_IS_NARROWING (uint64_t, uint8_t)
479  TRAIT_IS_NARROWING (uint32_t, uint16_t)
480  TRAIT_IS_NARROWING (uint32_t, uint8_t)
481  TRAIT_IS_NARROWING (uint16_t, uint8_t)
482  TRAIT_IS_NARROWING (uint16_t, ushort)
483 
484  TRAIT_IS_NARROWING (double, float)
485 
486  TRAIT_IS_NARROWING (double, lib::time::TimeValue)
487  TRAIT_IS_NARROWING (double, lib::time::Duration)
488 
489 #undef TRAIT_IS_NARROWING
490 
491 
492 
493 
494 
495 
496  /* ====== generic iteration support ====== */
497 
504  template<typename T>
506  {
507  using Type = typename Strip<T>::Type;
508 
509  META_DETECT_NESTED(value_type);
512 
513  public:
514  enum{ value = std::is_constructible<bool, Type>::value
515  and HasNested_value_type<Type>::value
516  and HasOperator_deref<Type>::value
517  and HasOperator_inc<Type>::value
518  };
519  };
520 
521 
522 
528  template<typename T>
530  {
531  using Type = typename Strip<T>::Type;
532 
533  META_DETECT_FUNCTION_ARGLESS(checkPoint);
536 
537  public:
538  enum{ value = HasArglessFun_checkPoint<Type>::value
539  and HasArglessFun_iterNext<Type>::value
540  and HasArglessFun_yield<Type>::value
541  };
542  };
543 
544 
545 
549  template<typename T>
551  {
552  using Type = typename Strip<T>::Type;
553 
554  struct is_iterable
555  {
556  META_DETECT_NESTED(iterator);
557  META_DETECT_FUNCTION(typename X::iterator, begin,(void));
558  META_DETECT_FUNCTION(typename X::iterator, end ,(void));
559 
560  enum { value = HasNested_iterator<Type>::value
561  and HasFunSig_begin<Type>::value
562  and HasFunSig_end<Type>::value
563  };
564  };
565 
567  {
568  META_DETECT_NESTED(iterator);
569  META_DETECT_FUNCTION(typename X::iterator, begin,(void) noexcept);
570  META_DETECT_FUNCTION(typename X::iterator, end ,(void) noexcept);
571 
572  enum { value = HasNested_iterator<Type>::value
573  and HasFunSig_begin<Type>::value
574  and HasFunSig_end<Type>::value
575  };
576  };
577 
579  {
580  META_DETECT_NESTED(const_iterator);
581  META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const);
582  META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const);
583 
584  enum { value = HasNested_const_iterator<Type>::value
585  and HasFunSig_begin<Type>::value
586  and HasFunSig_end<Type>::value
587  };
588  };
589 
591  {
592  META_DETECT_NESTED(const_iterator);
593  META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const noexcept);
594  META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const noexcept);
595 
596  enum { value = HasNested_const_iterator<Type>::value
597  and HasFunSig_begin<Type>::value
598  and HasFunSig_end<Type>::value
599  };
600  };
601 
602 
603  public:
604  enum { value = is_iterable::value
605  or is_const_iterable::value
606  or is_noexcept_iterable::value
607  or is_const_noexcept_iterable::value
608  };
609  };
610 
611 
613  template<typename T>
615  {
616  using Type = typename Strip<T>::Type;
617 
619  {
620  META_DETECT_NESTED(reverse_iterator);
621  META_DETECT_FUNCTION(typename X::reverse_iterator, rbegin,(void));
622  META_DETECT_FUNCTION(typename X::reverse_iterator, rend ,(void));
623 
624  enum { value = HasNested_reverse_iterator<Type>::value
625  and HasFunSig_rbegin<Type>::value
626  and HasFunSig_rend<Type>::value
627  };
628  };
629 
631  {
632  META_DETECT_NESTED(reverse_iterator);
633  META_DETECT_FUNCTION(typename X::reverse_iterator, rbegin,(void) noexcept);
634  META_DETECT_FUNCTION(typename X::reverse_iterator, rend ,(void) noexcept);
635 
636  enum { value = HasNested_reverse_iterator<Type>::value
637  and HasFunSig_rbegin<Type>::value
638  and HasFunSig_rend<Type>::value
639  };
640  };
641 
643  {
644  META_DETECT_NESTED(const_reverse_iterator);
645  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rbegin,(void) const);
646  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rend ,(void) const);
647 
648  enum { value = HasNested_const_reverse_iterator<Type>::value
649  and HasFunSig_rbegin<Type>::value
650  and HasFunSig_rend<Type>::value
651  };
652  };
653 
655  {
656  META_DETECT_NESTED(const_reverse_iterator);
657  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rbegin,(void) const noexcept);
658  META_DETECT_FUNCTION(typename X::const_reverse_iterator, rend ,(void) const noexcept);
659 
660  enum { value = HasNested_const_reverse_iterator<Type>::value
661  and HasFunSig_rbegin<Type>::value
662  and HasFunSig_rend<Type>::value
663  };
664  };
665 
666 
667  public:
668  enum { value = is_backIterable::value
669  or is_const_backIterable::value
670  or is_noexcept_backIterable::value
671  or is_const_noexcept_backIterable::value
672  };
673  };
674 
675 
676 
677 }} // namespace lib::meta
678 #endif
A refcounting Handle to an MObject of type MO, used to constrain or explicitly specify the location w...
Definition: trait.hpp:91
#define META_DETECT_OPERATOR_INC()
Detector for a prefix increment operator.
Definition: trait.hpp:69
Trait template to detect a type usable with the STL for-each loop.
Definition: trait.hpp:550
Trait template to detect a type also supporting STL-style backwards iteration.
Definition: trait.hpp:614
Representation of the result of some operation, EITHER a value or a failure.
Definition: result.hpp:106
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:529
types able to be lexically converted to string representation
Definition: trait.hpp:368
Helper for type analysis and convenience accessors: attempts to extract a base type from various wrap...
Definition: trait.hpp:128
compare for unadorned base type, disregarding const and references
Definition: trait.hpp:329
verify the first (special) type can stand-in for the second
Definition: trait.hpp:336
#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:389
Helper for type analysis: tries to strip all kinds of type adornments.
Definition: trait.hpp:249
Trait template to detect a type usable immediately as "Lumiera Forward Iterator" in a specialised for...
Definition: trait.hpp:505
#define META_DETECT_OPERATOR_DEREF()
Detector for a dereferentiation operator.
compare unadorned types, disregarding const and references
Definition: trait.hpp:311
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:443
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:477
Unwrap< X >::Type & unwrap(X const &wrapped)
convenience shortcut: unwrapping free function.
Definition: trait.hpp:239
#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:80
detect smart pointers
Definition: trait.hpp:400
Type definition helper for pointer and reference types.
Definition: trait.hpp:270
detect various flavours of string / text data
Definition: trait.hpp:344
verify compliance to an interface by subtype check
Definition: trait.hpp:318
basic constant internal time value.
Definition: timevalue.hpp:142
Metaprogramming helpers to check for specific properties of a type in question.