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) Lumiera.org
5  2008, 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 
37 #ifndef LIB_META_UTIL_H
38 #define LIB_META_UTIL_H
39 
40 #include "lib/integral.hpp"
41 
42 #include <typeinfo>
43 #include <string>
44 
45 namespace std {
46 
47  // forward declarations for common smart ptrs
48  template<typename T>
49  class shared_ptr;
50 
51  template <typename T, typename D>
52  class unique_ptr;
53 
54 }
55 
56 
57 
58 namespace lib {
59  class Literal;
60  class Symbol;
61 
62 namespace meta {
63 
64  /* === conditional definition selector === */
65 
66  template <bool B, class T = void>
67  struct enable_if_c {
68  typedef T type;
69  };
70 
71  template <class T>
72  struct enable_if_c<false, T> {};
73 
74 
91  template <class Cond, class T = void>
92  using enable_if = typename enable_if_c<Cond::value, T>::type;
93 
94  template <class Cond, class T = void>
95  using disable_if = typename enable_if_c<not Cond::value, T>::type;
96 
97 
98 
99 
100  /* === building metafunctions === */
101 
104  typedef char Yes_t;
105  struct No_t { char more_than_one[4]; };
106 
107 
108 
109 
110  namespace {
118  template<typename TY>
120  {
121  template<class ZZ>
122  static Yes_t check(typename ZZ::type *);
123  template<class X>
124  static Yes_t check(typename X::Type *);
125  template<class>
126  static No_t check(...);
127 
128  public:
129  static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
130  };
131 
132  }
134  template<typename X>
135  struct has_TypeResult : std::bool_constant<_DetectNested_TypeResult<X>::value> { };
136 
137 
138 
139  namespace {
140  template<typename...>
142  {
143  using Type = void;
144  };
145  template<typename X, typename...XS>
146  struct _ExtractFirst<X,XS...>
147  {
148  using Type = X;
149  };
150  }
152  template<typename...XS>
153  using extractFirst_t = typename _ExtractFirst<XS...>::Type;
154 
155 
156 
158  template<class SELF, typename ...ARGS>
159  using disable_if_self = disable_if<std::is_same<std::remove_cv_t<std::remove_reference_t<extractFirst_t<ARGS...>>>
160  , SELF>>;
161 
162 
163 
171  template<typename X>
173  {
174 
175  static Yes_t check_implicit(std::string);
176  static Yes_t check_implicit(std::string_view);
177  static Yes_t check_implicit(const char*);
178  static No_t check_implicit(...);
179 
180 
181  template<class XX, int i = sizeof(&XX::operator std::string)>
182  struct Probe
183  { };
184 
185  template <class XX>
186  static Yes_t check_explicit(Probe<XX> * );
187  template <class>
188  static No_t check_explicit(...);
189 
190  public:
191  static const bool value = (sizeof(Yes_t)==sizeof(check_implicit (std::declval<X>())))
192  or (sizeof(Yes_t)==sizeof(check_explicit<X>(0)));
193  };
194 
196  template<typename X>
198 
199 
200 
201 
207  template<typename TY>
209  {
210  template<class X>
211  static Yes_t check(typename X::List *);
212  template<class>
213  static No_t check(...);
214 
215  public:
216  static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0)));
217  };
218 
219 
223  template<typename FUN>
225  {
226  template<typename FF,
227  typename SEL = decltype(&FF::operator())>
228  struct Probe
229  { };
230 
231  template<class X>
232  static Yes_t check(Probe<X> * );
233  template<class>
234  static No_t check(...);
235 
236  public:
237  static const bool value = (sizeof(Yes_t)==sizeof(check<FUN>(0)));
238  };
239 
240 
247  template<class BAS, size_t m=0>
248  struct Marked
249  : BAS
250  {
251  using BAS::BAS;
252  };
253 
254 
255 
256 
257 
258 
259 
260 
261  /* ==== generic string representation ==== */
262 
266  std::string humanReadableTypeID (lib::Literal);
267 
272  std::string primaryTypeComponent (lib::Literal);
273 
275  std::string sanitisedFullTypeName(lib::Literal);
276 
281  std::string sanitisedSymbol(std::string const&);
282 
292  std::string demangleCxx (lib::Literal rawName);
293 
294 
295  extern const std::string FUNCTION_INDICATOR;
296  extern const std::string FAILURE_INDICATOR;
297  extern const std::string BOTTOM_INDICATOR;
298  extern const std::string VOID_INDICATOR;
299 
300  extern const std::string BOOL_FALSE_STR;
301  extern const std::string BOOL_TRUE_STR;
302 
303 
323  template<typename TY>
324  inline std::string
325  typeStr (TY const* obj =nullptr) noexcept
326  try {
327  auto mangledType = obj? typeid(*obj).name()
328  : typeid(TY).name();
329  return humanReadableTypeID (mangledType);
330  }
331  catch(...)
332  { return FAILURE_INDICATOR; }
333 
334  template<typename TY>
335  inline disable_if<std::is_pointer<TY>,
336  std::string >
337  typeStr (TY const& ref) noexcept
338  {
339  return typeStr (&ref);
340  }
341 
342  inline std::string
343  typeStr (void const*) noexcept
344  {
345  return VOID_INDICATOR;
346  }
347 
348 
349 
350 
355  template<typename TY>
356  inline std::string
357  typeSymbol (TY const* obj =nullptr)
358  {
359  auto mangledType = obj? typeid(*obj).name()
360  : typeid(TY).name();
361  return primaryTypeComponent (mangledType);
362  }
363 
364  template<typename TY>
365  inline disable_if<std::is_pointer<TY>,
366  std::string >
367  typeSymbol (TY const& ref)
368  {
369  return typeSymbol (&ref);
370  }
371 
372 }}// namespace lib::meta
373 
374 
375 
376 
377 namespace util {
378 
379  using lib::meta::typeStr;
380  using lib::meta::FAILURE_INDICATOR;
381  using lib::meta::BOTTOM_INDICATOR;
382 
383 
398  template<typename X, typename COND =void>
399  struct StringConv
400  {
401  static std::string
402  invoke (X const& x) noexcept
403  try { return "«"+typeStr(x)+"»"; }
404  catch(...) { return FAILURE_INDICATOR; }
405  };
406 
407  template<typename X>
408  struct StringConv<X, lib::meta::enable_CustomStringConversion<X>>
409  {
410  static std::string
411  invoke (X const& val) noexcept
412  try { return std::string(val); }
413  catch(...) { return FAILURE_INDICATOR; }
414  };
415 
421  template<typename X>
422  struct StringConv<X*, lib::meta::disable_if<std::__or_<std::is_same<std::remove_cv_t<X>, char>
423  ,std::is_same<std::remove_cv_t<X>, void>
424  > >>
425  {
426  static std::string
427  invoke (X const* ptr) noexcept
428  try { return ptr? "↗" + StringConv<X>::invoke(*ptr)
429  : BOTTOM_INDICATOR + "«"+typeStr(ptr)+"»";
430  }
431  catch(...) { return FAILURE_INDICATOR; }
432  };
433 
434  // NOTE: this is meant to be extensible;
435  // more specialisations are e.g. in format-obj.hpp
436 
437 
438 
439 
443  inline std::string
444  showBool (bool yes) noexcept
445  {
446  return yes? lib::meta::BOOL_TRUE_STR
447  : lib::meta::BOOL_FALSE_STR;
448  }
449 
451  std::string showDouble (double) noexcept;
452  std::string showFloat (float) noexcept;
453 
455  std::string showDecimal (double) noexcept;
456  std::string showDecimal (float) noexcept;
457  std::string showDecimal (f128) noexcept;
458 
460  std::string showComplete (double) noexcept;
461  std::string showComplete (float) noexcept;
462  std::string showComplete (f128) noexcept;
463 
464  std::string showSize (size_t) noexcept;
465 
466 
467 
469  std::string showAddr (void const* addr) noexcept;
470 
471  template<typename X>
472  inline std::string
473  showAddr (X& elm) noexcept
474  {
475  return showAddr(&elm);
476  }
477 
478 
480  template<typename X>
481  inline std::string
482  showPtr (X* ptr =nullptr)
483  {
484  return ptr? showAddr(ptr) + " ↗" + StringConv<X>::invoke(*ptr)
485  : BOTTOM_INDICATOR + " «" + typeStr(ptr) + "»";
486  }
487 
488  template<typename SP>
489  inline std::string
490  showSmartPtr (SP const& smPtr, std::string label = "smP")
491  {
492  using TargetType = typename SP::element_type;
493 
494  return smPtr? label+"("+showAddr(smPtr.get()) + ") ↗" + StringConv<TargetType>::invoke(*smPtr)
495  : BOTTOM_INDICATOR + " «" + typeStr(smPtr) + "»";
496  }
497 
498 
499 }// namespace util
500 
501 
502 
503 /* === Literals for common size designations === */
504 
505 inline uint
506 operator""_KiB (unsigned long long const siz)
507 {
508  return uint(siz) * 1024u;
509 }
510 
511 inline uint
512 operator""_MiB (unsigned long long const siz)
513 {
514  return uint(siz) * 1024u*1024u;
515 }
516 
517 inline unsigned long long
518 operator""_GiB (unsigned long long const siz)
519 {
520  return siz * 1024uLL*1024uLL*1024uLL;
521 }
522 
523 
524 #endif /*LIB_META_UTIL_H*/
ostream & showAddr(ostream &stream, void const *addr)
preconfigured format for pretty-printing of addresses
Definition: format-obj.cpp:387
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
string showComplete(double val) noexcept
show enough decimal digits to represent every distinct value
Definition: format-obj.cpp:369
STL namespace.
string showDouble(double val) noexcept
pretty-print a double in (rounded) fixed-point format
Definition: format-obj.cpp:362
helper to check if another metafunction produced a result type
Definition: meta/util.hpp:135
string showDecimal(double val) noexcept
show maximum reproducible decimal representation
Definition: format-obj.cpp:365
std::string showBool(bool yes) noexcept
human readable display of boolean values
Definition: meta/util.hpp:444
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:92
string primaryTypeComponent(Literal rawType)
extract core name component from a raw type spec
Definition: format-obj.cpp:270
enable_if< can_convertToString< X > > enable_CustomStringConversion
toggle for explicit specialisations
Definition: meta/util.hpp:197
string sanitisedFullTypeName(lib::Literal rawName)
build a sanitised ID from full type name
Definition: format-obj.cpp:308
string demangleCxx(Literal rawName)
Fallback type-ID:
Definition: format-obj.cpp:168
Trait template for detecting a typelist type.
Definition: meta/util.hpp:208
char Yes_t
helper types to detect the overload resolution chosen by the compiler
Definition: meta/util.hpp:104
string humanReadableTypeID(Literal rawType)
pretty-print an internal C++ type representation
Definition: format-obj.cpp:199
detect possibility of a conversion to string.
Definition: meta/util.hpp:172
Metaprogramming helper to mark some arbitrary base type by subclassing.
Definition: meta/util.hpp:248
string sanitisedSymbol(string const &text)
condense a string and retain only valid identifiers
Definition: format-obj.cpp:315
std::string showPtr(X *ptr=nullptr)
diagnostics helper for explicitly indicating pointers
Definition: meta/util.hpp:482
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:399
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:160
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
Definition: meta/util.hpp:325
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:153
Trait template to detect presence of a simple function call operator.
Definition: meta/util.hpp:224