Lumiera  0.pre.03
»edit your freedom«
meta/util.hpp
Go to the documentation of this file.
1 /*
2  UTIL.hpp - metaprogramming helpers and utilities
3 
4  Copyright (C)
5  2008, 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 
28 #ifndef LIB_META_UTIL_H
29 #define LIB_META_UTIL_H
30 
31 #include "lib/integral.hpp"
32 
33 #include <typeinfo>
34 #include <string>
35 
36 namespace std {
37 
38  // forward declarations for common smart ptrs
39  template<typename T>
40  class shared_ptr;
41 
42  template <typename T, typename D>
43  class unique_ptr;
44 
45 }
46 
47 
48 
49 namespace lib {
50  class Literal;
51  class Symbol;
52 
53 namespace meta {
54 
55  /* === conditional definition selector === */
56 
57  template <bool B, class T = void>
58  struct enable_if_c {
59  typedef T type;
60  };
61 
62  template <class T>
63  struct enable_if_c<false, T> {};
64 
65 
82  template <class Cond, class T = void>
83  using enable_if = typename enable_if_c<Cond::value, T>::type;
84 
85  template <class Cond, class T = void>
86  using disable_if = typename enable_if_c<not Cond::value, T>::type;
87 
88 
89 
90 
91  /* === building metafunctions === */
92 
95  typedef char Yes_t;
96  struct No_t { char more_than_one[4]; };
97 
98 
99 
100 
101  namespace {
109  template<typename TY>
111  {
112  template<class ZZ>
113  static Yes_t check(typename ZZ::type *);
114  template<class X>
115  static Yes_t check(typename X::Type *);
116  template<class>
117  static No_t check(...);
118 
119  public:
120  static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
121  };
122 
123  }
125  template<typename X>
126  struct has_TypeResult : std::bool_constant<_DetectNested_TypeResult<X>::value> { };
127 
128 
129 
130  namespace {
131  template<typename...>
133  {
134  using Type = void;
135  };
136  template<typename X, typename...XS>
137  struct _ExtractFirst<X,XS...>
138  {
139  using Type = X;
140  };
141  }
143  template<typename...XS>
144  using extractFirst_t = typename _ExtractFirst<XS...>::Type;
145 
146 
147 
149  template<class SELF, typename ...ARGS>
150  using disable_if_self = disable_if<std::is_same<std::remove_cv_t<std::remove_reference_t<extractFirst_t<ARGS...>>>
151  , SELF>>;
152 
153 
154 
162  template<typename X>
164  {
165 
166  static Yes_t check_implicit(std::string);
167  static Yes_t check_implicit(std::string_view);
168  static Yes_t check_implicit(const char*);
169  static No_t check_implicit(...);
170 
171 
172  template<class XX, int i = sizeof(&XX::operator std::string)>
173  struct Probe
174  { };
175 
176  template <class XX>
177  static Yes_t check_explicit(Probe<XX> * );
178  template <class>
179  static No_t check_explicit(...);
180 
181  public:
182  static const bool value = (sizeof(Yes_t)==sizeof(check_implicit (std::declval<X>())))
183  or (sizeof(Yes_t)==sizeof(check_explicit<X>(0)));
184  };
185 
187  template<typename X>
189 
190 
191 
192 
198  template<typename TY>
200  {
201  template<class X>
202  static Yes_t check(typename X::List *);
203  template<class>
204  static No_t check(...);
205 
206  public:
207  static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
208  };
209 
210 
214  template<typename FUN>
216  {
217  template<typename FF,
218  typename SEL = decltype(&FF::operator())>
219  struct Probe
220  { };
221 
222  template<class X>
223  static Yes_t check(Probe<X> * );
224  template<class>
225  static No_t check(...);
226 
227  public:
228  static const bool value = (sizeof(Yes_t)==sizeof(check<FUN>(0)));
229  };
230 
231 
238  template<class BAS, size_t m=0>
239  struct Marked
240  : BAS
241  {
242  using BAS::BAS;
243  };
244 
245 
246 
247 
248 
249 
250 
251 
252  /* ==== generic string representation ==== */
253 
257  std::string humanReadableTypeID (lib::Literal);
258 
263  std::string primaryTypeComponent (lib::Literal);
264 
266  std::string sanitisedFullTypeName(lib::Literal);
267 
272  std::string sanitisedSymbol(std::string const&);
273 
283  std::string demangleCxx (lib::Literal rawName);
284 
285 
286  extern const std::string FUNCTION_INDICATOR;
287  extern const std::string FAILURE_INDICATOR;
288  extern const std::string BOTTOM_INDICATOR;
289  extern const std::string VOID_INDICATOR;
290 
291  extern const std::string BOOL_FALSE_STR;
292  extern const std::string BOOL_TRUE_STR;
293 
294 
314  template<typename TY>
315  inline std::string
316  typeStr (TY const* obj =nullptr) noexcept
317  try {
318  auto mangledType = obj? typeid(*obj).name()
319  : typeid(TY).name();
320  return humanReadableTypeID (mangledType);
321  }
322  catch(...)
323  { return FAILURE_INDICATOR; }
324 
325  template<typename TY>
326  inline disable_if<std::is_pointer<TY>,
327  std::string >
328  typeStr (TY const& ref) noexcept
329  {
330  return typeStr (&ref);
331  }
332 
333  inline std::string
334  typeStr (void const*) noexcept
335  {
336  return VOID_INDICATOR;
337  }
338 
339 
340 
341 
346  template<typename TY>
347  inline std::string
348  typeSymbol (TY const* obj =nullptr)
349  {
350  auto mangledType = obj? typeid(*obj).name()
351  : typeid(TY).name();
352  return primaryTypeComponent (mangledType);
353  }
354 
355  template<typename TY>
356  inline disable_if<std::is_pointer<TY>,
357  std::string >
358  typeSymbol (TY const& ref)
359  {
360  return typeSymbol (&ref);
361  }
362 
363 }}// namespace lib::meta
364 
365 
366 
367 
368 namespace util {
369 
370  using lib::meta::typeStr;
371  using lib::meta::FAILURE_INDICATOR;
372  using lib::meta::BOTTOM_INDICATOR;
373 
374 
389  template<typename X, typename COND =void>
390  struct StringConv
391  {
392  static std::string
393  invoke (X const& x) noexcept
394  try { return "«"+typeStr(x)+"»"; }
395  catch(...) { return FAILURE_INDICATOR; }
396  };
397 
398  template<typename X>
399  struct StringConv<X, lib::meta::enable_CustomStringConversion<X>>
400  {
401  static std::string
402  invoke (X const& val) noexcept
403  try { return std::string(val); }
404  catch(...) { return FAILURE_INDICATOR; }
405  };
406 
412  template<typename X>
413  struct StringConv<X*, lib::meta::disable_if<std::__or_<std::is_same<std::remove_cv_t<X>, char>
414  ,std::is_same<std::remove_cv_t<X>, void>
415  > >>
416  {
417  static std::string
418  invoke (X const* ptr) noexcept
419  try { return ptr? "↗" + StringConv<X>::invoke(*ptr)
420  : BOTTOM_INDICATOR + "«"+typeStr(ptr)+"»";
421  }
422  catch(...) { return FAILURE_INDICATOR; }
423  };
424 
425  // NOTE: this is meant to be extensible;
426  // more specialisations are e.g. in format-obj.hpp
427 
428 
429 
430 
434  inline std::string
435  showBool (bool yes) noexcept
436  {
437  return yes? lib::meta::BOOL_TRUE_STR
438  : lib::meta::BOOL_FALSE_STR;
439  }
440 
442  std::string showDouble (double) noexcept;
443  std::string showFloat (float) noexcept;
444 
446  std::string showDecimal (double) noexcept;
447  std::string showDecimal (float) noexcept;
448  std::string showDecimal (f128) noexcept;
449 
451  std::string showComplete (double) noexcept;
452  std::string showComplete (float) noexcept;
453  std::string showComplete (f128) noexcept;
454 
455  std::string showSize (size_t) noexcept;
456 
457 
458 
460  std::string showAdr (void const* addr) noexcept;
461 
462  template<typename X>
463  inline lib::meta::disable_if<std::is_pointer<X>,
464  std::string >
465  showAdr (X& elm) noexcept
466  {
467  return showAdr(&elm);
468  }
469 
470 
472  template<typename X>
473  inline std::string
474  showPtr (X* ptr =nullptr)
475  {
476  return ptr? showAdr(ptr) + " ↗" + StringConv<X>::invoke(*ptr)
477  : BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»";
478  }
479 
480  template<typename SP>
481  inline std::string
482  showSmartPtr (SP const& smPtr, std::string label = "smP")
483  {
484  using TargetType = typename SP::element_type;
485 
486  return smPtr? label+"("+showAdr(smPtr.get()) + ") ↗" + StringConv<TargetType>::invoke(*smPtr)
487  : BOTTOM_INDICATOR + " «" + typeStr(smPtr) + "»";
488  }
489 
490 
491 }// namespace util
492 
493 
494 
495 /* === Literals for common size designations === */
496 
497 inline uint
498 operator""_KiB (ullong const siz)
499 {
500  return uint(siz) * 1024u;
501 }
502 
503 inline uint
504 operator""_MiB (ullong const siz)
505 {
506  return uint(siz) * 1024u*1024u;
507 }
508 
509 inline ullong
510 operator""_GiB (ullong const siz)
511 {
512  return siz * 1024uLL*1024uLL*1024uLL;
513 }
514 
515 
516 #endif /*LIB_META_UTIL_H*/
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
string showComplete(double val) noexcept
show enough decimal digits to represent every distinct value
Definition: format-obj.cpp:367
STL namespace.
string showDouble(double val) noexcept
pretty-print a double in (rounded) fixed-point format
Definition: format-obj.cpp:360
helper to check if another metafunction produced a result type
Definition: meta/util.hpp:126
string showDecimal(double val) noexcept
show maximum reproducible decimal representation
Definition: format-obj.cpp:363
std::string showBool(bool yes) noexcept
human readable display of boolean values
Definition: meta/util.hpp:435
Implementation namespace for support and library code.
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:83
string primaryTypeComponent(Literal rawType)
extract core name component from a raw type spec
Definition: format-obj.cpp:268
enable_if< can_convertToString< X > > enable_CustomStringConversion
toggle for explicit specialisations
Definition: meta/util.hpp:188
string sanitisedFullTypeName(lib::Literal rawName)
build a sanitised ID from full type name
Definition: format-obj.cpp:306
string demangleCxx(Literal rawName)
Fallback type-ID:
Definition: format-obj.cpp:159
Trait template for detecting a typelist type.
Definition: meta/util.hpp:199
char Yes_t
helper types to detect the overload resolution chosen by the compiler
Definition: meta/util.hpp:95
string humanReadableTypeID(Literal rawType)
pretty-print an internal C++ type representation
Definition: format-obj.cpp:190
detect possibility of a conversion to string.
Definition: meta/util.hpp:163
Metaprogramming helper to mark some arbitrary base type by subclassing.
Definition: meta/util.hpp:239
string sanitisedSymbol(string const &text)
condense a string and retain only valid identifiers
Definition: format-obj.cpp:313
std::string showPtr(X *ptr=nullptr)
diagnostics helper for explicitly indicating pointers
Definition: meta/util.hpp:474
ostream & showAdr(ostream &stream, void const *addr)
preconfigured format for pretty-printing of addresses
Definition: format-obj.cpp:385
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:390
disable_if< std::is_same< std::remove_cv_t< std::remove_reference_t< extractFirst_t< ARGS... > >>, SELF > > disable_if_self
helper to prevent a template constructor from shadowing inherited copy ctors
Definition: meta/util.hpp:151
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
Definition: meta/util.hpp:316
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption
typename _ExtractFirst< XS... >::Type extractFirst_t
helper to extract the first argument from a variadic arg pack, if any
Definition: meta/util.hpp:144
Trait template to detect presence of a simple function call operator.
Definition: meta/util.hpp:215