Classdesc 3.44
classdesc.h
1/*
2 @copyright Russell Standish 2000-2013
3 @author Russell Standish
4 This file is part of Classdesc
5
6 Open source licensed under the MIT license. See LICENSE for details.
7*/
8
9#ifndef CLASSDESC_H
10#define CLASSDESC_H
11
12// given this is a header-only library, there shouldn't be an issue of
13// differing standards for name mangling between caller and callee
14#if defined(__GNUC__) && !defined(__ICC)
15#pragma GCC diagnostic push
16#pragma GCC diagnostic ignored "-Wnoexcept-type"
17#endif
18
19
20// ensure link time failure if classdesc_epilogue.h not included
21namespace
22{
23 int classdesc_epilogue_not_included();
24 int _dummy=classdesc_epilogue_not_included();
25}
26
27#include <string>
28#include <sstream>
29#include <map>
30#include <cmath>
31#include <cstddef>
32#include <stdexcept>
33#include <memory>
34#include <climits>
35#include <iostream>
36
37#ifdef __EMSCRIPTEN__
38#include <emscripten/console.h>
39#endif
40
41#ifdef __CYGWIN__
42namespace std
43{
44 //missing in Cygwin?
45 typedef basic_string<wchar_t> wstring;
46}
47#endif
48
49#include <vector>
50#include <deque>
51#include <list>
52#include <set>
53#include <map>
54#if defined(__cplusplus) && __cplusplus>=201103L
55#include <unordered_map>
56#include <unordered_set>
57#endif
58
59
60#if defined(__cplusplus) && __cplusplus<201103L
61/*
62 Classdesc is now dependent on TR1. These can either
63 be obtained from the compiler's standard library, or from Boost.
64 TODO: check that this works with Boost!
65*/
66#ifdef TR1
67#include <tr1/type_traits>
68#if !defined(__ICC) || __ICC > 1100 //tr1 shared_ptr impl not functional with icc 10.1
69#include <tr1/memory>
70#endif
71#elif BOOST_TR1
72#include <boost/tr1/type_traits.hpp>
73#include <boost/tr1/memory.hpp>
74#endif
75#endif
76
80
81#if defined(__cplusplus) && __cplusplus>=201103L || defined(_MSC_VER)
82
83#include <unordered_map>
84#include <unordered_set>
85
86#include <type_traits>
87#include <functional>
88
89namespace classdesc
90{
91 using std::true_type;
92 using std::false_type;
93
94 using std::is_void;
95 using std::is_integral;
96 using std::is_floating_point;
97 // is_arry conflicts with an already established classdesc concept
98 // using std::is_array;
99 template <class T>
100 struct is_Carray: public std::is_array<T> {};
101 using std::is_pointer;
102 using std::is_reference;
103 using std::is_member_object_pointer;
104 using std::is_member_function_pointer;
105 using std::is_enum;
106 using std::is_union;
107 using std::is_class;
108 using std::is_function;
109
110 using std::is_arithmetic;
111 using std::is_fundamental;
112 using std::is_object;
113 using std::is_scalar;
114 using std::is_compound;
115 using std::is_member_pointer;
116
117 using std::is_const;
118 using std::is_volatile;
119 using std::is_pod;
120 using std::is_empty;
121 using std::is_polymorphic;
122 using std::is_abstract;
123 using std::is_signed;
124 using std::is_unsigned;
125 using std::alignment_of;
126 // conflicts with ecolab definition
127 // using std::rank;
128 using std::extent;
129
130 using std::is_same;
131 using std::is_base_of;
132 using std::is_convertible;
133
134 using std::remove_const;
135 using std::remove_volatile;
136 using std::remove_cv;
137 using std::add_const;
138 using std::add_volatile;
139 using std::add_cv;
140
141 using std::remove_reference;
142
143 using std::remove_extent;
144 using std::remove_all_extents;
145
146 using std::remove_pointer;
147 using std::add_pointer;
148
149 using std::shared_ptr;
150 using std::weak_ptr;
151 using std::dynamic_pointer_cast;
152
153 using std::is_default_constructible;
154 using std::is_copy_constructible;
155 using std::is_assignable;
156
157 // useful utility for SFINAE calculations
158 // See https://isocpp.org/files/papers/N3911.pdf
159 template <typename... > using void_t = void;
160
161 // missing from std, so supply here in classdesc
162 template <class T, class... Args>
163 std::unique_ptr<T> make_unique(Args... args)
164 {return std::unique_ptr<T>(new T(args...));}
165}
166
167// long long is now part of the standard language
168#ifndef HAVE_LONGLONG
169#define HAVE_LONGLONG
170#endif
171
172#elif defined(BOOST_TR1) || defined(TR1)
173namespace classdesc
174{
175 using std::tr1::true_type;
176 using std::tr1::false_type;
177
178 using std::tr1::is_void;
179 using std::tr1::is_integral;
180 using std::tr1::is_floating_point;
181 // conflicts with an already established classdesc concept
182 //using std::tr1::is_array;
183 template <class T>
184 struct is_Carray: public std::tr1::is_array<T> {};
185 using std::tr1::is_pointer;
186 using std::tr1::is_reference;
187 using std::tr1::is_member_object_pointer;
188 using std::tr1::is_member_function_pointer;
189 using std::tr1::is_enum;
190 using std::tr1::is_union;
191 using std::tr1::is_class;
192 using std::tr1::is_function;
193
194 using std::tr1::is_arithmetic;
195 using std::tr1::is_fundamental;
196 using std::tr1::is_object;
197 using std::tr1::is_scalar;
198 using std::tr1::is_compound;
199 using std::tr1::is_member_pointer;
200
201 using std::tr1::is_const;
202 using std::tr1::is_volatile;
203 using std::tr1::is_pod;
204 using std::tr1::is_empty;
205 using std::tr1::is_polymorphic;
206 using std::tr1::is_abstract;
207 using std::tr1::is_signed;
208 using std::tr1::is_unsigned;
209 using std::tr1::alignment_of;
210 // conflicts with ecolab definition
211 // using std::tr1::rank;
212 using std::tr1::extent;
213
214 using std::tr1::is_same;
215 using std::tr1::is_base_of;
216 using std::tr1::is_convertible;
217
218 using std::tr1::remove_const;
219 using std::tr1::remove_volatile;
220 using std::tr1::remove_cv;
221 using std::tr1::add_const;
222 using std::tr1::add_volatile;
223 using std::tr1::add_cv;
224
225 using std::tr1::remove_reference;
226
227 using std::tr1::remove_extent;
228 using std::tr1::remove_all_extents;
229
230 using std::tr1::remove_pointer;
231 using std::tr1::add_pointer;
232
233 // nb ultimately, all compilers will support std::shared_ptr, but
234 // until then, this bit of ugly hackery is required.
235#if (!defined(__ICC) || __ICC > 1100)
236 using std::tr1::shared_ptr;
237 using std::tr1::weak_ptr;
238 using std::tr1::dynamic_pointer_cast;
239#endif
240
241 // fake these using TR1 counterparts (which are conservative)
242 template <class T> struct is_default_constructible:
243
244 public std::tr1::has_nothrow_constructor<T> {};
245 template <class T> struct is_copy_constructible:
246 public std::tr1::has_nothrow_copy<T> {};
247 template <class T, class U> struct is_assignable
248 {
249 static const bool value=std::tr1::has_nothrow_assign<T>::value &&
250 std::tr1::is_convertible<U,T>::value;
251 };
252
253// // ensure at least strings work!
254// template <class C, class A>
255// struct is_default_constructible<std::basic_string<C,A> >:
256// public std::tr1::true_type {};
257// template <class C, class A>
258// struct is_copy_constructible<std::basic_string<C,A> >:
259// public std::tr1::true_type {};
260// template <class C, class A, class U>
261// struct is_assignable<std::basic_string<C,A>, U>
262// {
263// static const bool value=
264// std::tr1::is_convertible<U,std::basic_string<C,A> >::value;
265// };
266}
267
268#endif
269
270
271namespace classdesc
272{
273 using std::string;
274 template <bool, class type=void> struct enable_if_c {typedef type T;};
275 template <class T> struct enable_if_c<false,T> {};
277
281 template <class Cond, class T=void> struct enable_if:
282 public enable_if_c<Cond::value,T> {};
283
284#undef True
285 // NB - implementation of C++11 std::conditional
286 template <bool C, class True, class F>
288 {
289 typedef True T;
290 };
291
292 template <class True, class F>
293 struct conditional<false, True, F>
294 {
295 typedef F T;
296 };
297
298 // to help distinguish functions templates on old compilers (eg gcc 3.2)
299 template <int> struct dummy {dummy(int) {} };
300
302 template <class T> struct is_sequence {static const bool value=false;};
303 template <class T, class A> struct is_sequence<std::vector<T,A> > {
304 static const bool value=true;};
305 template <class T, class A> struct is_sequence<std::deque<T,A> > {
306 static const bool value=true;};
307 template <class T, class A> struct is_sequence<std::list<T,A> > {
308 static const bool value=true;};
309 template <class T> struct is_sequence<const T>: public is_sequence<T> {};
311
313 template <class T> struct is_string {static const bool value=false;};
314 template <class T> struct is_string<std::basic_string<T> >
315 {static const bool value=true;};
316 template <class T> struct is_string<const T>: public is_string<T> {};
318
320 template <class T>
321 struct is_associative_container {static const bool value=false;};
322 template <class T, class C, class A>
323 struct is_associative_container<std::set<T,C,A> > {
324 static const bool value=true;};
325 template <class K, class V, class C, class A>
326 struct is_associative_container<std::map<K,V,C,A> > {
327 static const bool value=true;};
328 template <class T, class C, class A>
329 struct is_associative_container<std::multiset<T,C,A> > {
330 static const bool value=true;};
331 template <class K, class V, class C, class A>
332 struct is_associative_container<std::multimap<K,V,C,A> > {
333 static const bool value=true;};
334
335#if defined(__cplusplus) && __cplusplus>=201103L
336 template <class T, class=void> struct is_iterator: public false_type {};
337 template <class T> struct is_iterator<T, void_t<typename std::iterator_traits<T>::iterator_category>>:
338 public true_type {};
339
340 template <class K, class V, class H, class P, class A>
341 struct is_associative_container<std::unordered_map<K,V,H,P,A> > {
342 static const bool value=true;};
343 template <class K, class H, class P, class A>
344 struct is_associative_container<std::unordered_set<K,H,P,A> > {
345 static const bool value=true;};
346 template <class K, class V, class H, class P, class A>
347 struct is_associative_container<std::unordered_multimap<K,V,H,P,A> > {
348 static const bool value=true;};
349 template <class K, class H, class P, class A>
350 struct is_associative_container<std::unordered_multiset<K,H,P,A> > {
351 static const bool value=true;};
352 template <class T, std::size_t N>
353 struct is_sequence<std::array<T,N>> {static const bool value=true;};
354#endif
355 template <class T> struct is_associative_container<const T>: public is_associative_container<T> {};
356
358 template <class T> struct is_container {
359 static const bool value=
360 is_sequence<T>::value||is_associative_container<T>::value;
361 };
362
364 template <class T> struct is_stringKeyMap: public false_type {};
365
367 template <class T> struct is_pair: public false_type {};
368 template <class F, class S> struct is_pair<std::pair<F,S> >: public true_type {};
369
371 template <class T> struct is_smart_ptr: public false_type {};
372 template <class T> struct is_smart_ptr<shared_ptr<T> >: public true_type {};
373 template <class T> struct is_smart_ptr<weak_ptr<T> >: public true_type {};
374 template <class T> struct is_smart_ptr<const shared_ptr<T> >: public true_type {};
375 template <class T> struct is_smart_ptr<const weak_ptr<T> >: public true_type {};
376#if defined(__cplusplus) && __cplusplus>=201103L
377 template <class T> struct is_smart_ptr<std::unique_ptr<T>>: public true_type {};
378 template <class T> struct is_smart_ptr<const std::unique_ptr<T>>: public true_type {};
379#endif
381
382 template <class T> struct is_weak_ptr: public false_type {};
383 template <class T> struct is_weak_ptr<weak_ptr<T> >: public true_type {};
384 template <class T> struct is_weak_ptr<const weak_ptr<T> >: public true_type {};
385
386#if defined(__cplusplus) && __cplusplus>=201103L
388 // modified slightly from StackOverflow answer https://stackoverflow.com/questions/21119281/using-sfinae-to-check-if-the-type-is-complete-or-not
389 template <typename T>
390 struct is_complete_helper {
391 template <typename U>
392 static auto test(U*) -> std::integral_constant<bool, sizeof(U) == sizeof(U)>;
393 static auto test(...) -> std::false_type;
394 using type = decltype(test((T*)0));
395 };
396
397 template <typename T>
398 struct is_complete : is_complete_helper<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type {};
400#endif
401
404 template <class T> struct Not
405 {static const bool value=!T::value;};
406
407#if defined(__cplusplus) && __cplusplus>=201103L
408 // variadic versions of the below conjunctions
409 template <class A, class... B> struct And
410 {static const bool value=A::value && And<B...>::value;};
411
412 template <class A> struct And<A> {static const bool value=A::value;};
413
414 template <class A, class... B> struct Or
415 {static const bool value=A::value || Or<B...>::value;};
416
417 template <class A> struct Or<A> {static const bool value=A::value;};
418#else
419 template <class A, class B> struct And
420 {static const bool value=A::value && B::value;};
421
422 template <class A, class B> struct Or
423 {static const bool value=A::value || B::value;};
424#endif
425
426 template <int X, int Y> struct Eq
427 {static const bool value=X==Y;};
428
429
431 template <class T, class U, bool c=Or<is_const<T>,is_const<U> >::value> struct transfer_const;
432 template <class T, class U> struct transfer_const<T,U,true>
433 {
434 typedef typename add_const<U>::type type;
435 };
436
437 template <class T, class U> struct transfer_const<T,U,false>
438 {
439 typedef typename remove_const<U>::type type;
440 };
441
444#define CLASSDESC_HAS_MEMBER(mem) \
445 template <class T, class Sig> \
446 struct has_member_##mem \
447 { \
448 template <class U, Sig> struct SFINAE {}; \
449 template <class U> static char test(SFINAE<U,&U::mem>*); \
450 template <class U> static int test(...); \
451 const static bool value=sizeof(test<T>(0))==sizeof(char); \
452 };
453
454 // handle resize on nonresizable containers such as std::array
455 CLASSDESC_HAS_MEMBER(resize);
456
457 template <class T>
459 public Or<has_member_resize<T,void (T::*)(typename T::size_type)>,
460 has_member_resize
461 <T,void (T::*)(typename T::size_type, typename T::value_type)> > {};
462
463 template <class T>
464 typename enable_if<has_resize<T>, void>::T
465 resize(T& x, size_t n) {x.resize(n);}
466
467 template <class T>
468 typename enable_if<Not<has_resize<T> >, void>::T
469 resize(T& x, size_t n) {}
470
471 CLASSDESC_HAS_MEMBER(push_back);
472 CLASSDESC_HAS_MEMBER(erase);
473
474 template <class T>
476 public Or<has_member_push_back<T,void (T::*)(typename T::value_type)>,
477 has_member_push_back
478 <T,void (T::*)(const typename T::value_type&)> > {};
479
480 template <class T>
482 push_back(T& x, const typename T::value_type& v) {x.push_back(v);}
483
484 template <class T>
485 typename enable_if<Or<Not<has_push_back<T> >,is_const<T> >, void>::T
486 push_back(T& x, const typename T::value_type& v) {}
487
488
489 CLASSDESC_HAS_MEMBER(size);
490 template <class T> struct has_size: public has_member_size<T,size_t (T::*)()const> {};
491 CLASSDESC_HAS_MEMBER(value_type);
492 template <class T> struct has_value_type: public has_member_value_type<T,size_t (T::*)()const> {};
493
494 // doesn't quite work :(
495// template <class T>
496// struct has_index_operator
497// {
498// template <class U, decltype(&U::operator[])> struct SFINAE {};
499// template <class U> static char test(SFINAE<U,&U::operator[]>*);
500// template <class U> static int test(...);
501// const static bool value=sizeof(test<T>(0))==sizeof(char);
502// };
503
504 // specialise this to enable python indexing
505 template <class T> struct has_index_operator: public false_type {};
506
507 // template <class T>
508 // typename enable_if<is_sequence<T>,void>::T
509 // resize(T& x, std::size_t n) {x.resize(n);}
510 //#if defined(__cplusplus) && __cplusplus>=201103L
511 // template <class T, std::size_t N>
512 // void resize(std::array<T,N>& x, std::size_t n) {}
513 //#endif
514
515
517
518 // is_assignable doesn't seem to be working correctly yet
519 // template <class T> struct is_dca:
520 // public And<And<is_default_constructible<T>, is_copy_constructible<T> >,
521 // is_assignable<T,T> > {};
522 template <class T> struct is_dca:
523 public And<is_default_constructible<T>, is_copy_constructible<T> > {};
524
526 template <class T> const T& keyOf(const T& x) {return x;}
527 template <class F, class S> const F& keyOf(const std::pair<F,S>& x) {return x.first;}
528
530 template <class T> struct is_rvalue
531 {
532 static const bool value=is_dca<T>::value && !is_abstract<T>::value;
533 };
534
535 template <class T> struct is_rvalue<T&>
536 {
537 static const bool value=false;
538 };
539
540 template <class T> struct is_rvalue<const T&>: public is_rvalue<T> {};
541
543
545 struct exception: std::runtime_error
546 {
547 exception(const string& s="classdesc exception"): std::runtime_error(s) {}
548 };
549
550#if defined(__cplusplus) && __cplusplus>=201103L
551 template <class Tp, class EqualTo>
552 struct has_equality_operator_impl
553 {
554 template <class U, class V>
555 static auto test(U*) -> decltype(std::declval<U>() == std::declval<V>());
556 template <typename, typename>
557 static auto test(...) -> std::false_type;
558 using type=typename std::is_same<bool, decltype(test<Tp, EqualTo>(0))>::type;
559 };
560 template <class T, class EqualTo=T>
561 struct has_equality_operator: public has_equality_operator_impl<T,EqualTo>::type {};
562
563 template <class T, class U>
564 struct has_equality_operator<std::pair<T,U>>:
565 public And<has_equality_operator<T>, has_equality_operator<U>> {};
566#endif
567
568 /*
569 Support for typeName functionality
570 */
571 template <class T, class Enable=void> struct tn; //for partial specialisation support
572 template <class T>
573 typename enable_if<
575 std::string>::T typeName();
576
577#if defined(__cplusplus) && __cplusplus>=201103L
578 // handle variadic arguments
579 template <class T, class... A> std::string varTn() {return typeName<T>()+","+varTn<A...>();}
580 template <class T> std::string varTn() {return typeName<T>();}
581#endif
582
584 template <> inline std::string typeName<void>() {return "void";}
585 template <> inline std::string typeName<bool>() {return "bool";}
586 template <> inline std::string typeName<char>() {return "char";}
587 template <> inline std::string typeName<short>() {return "short";}
588 template <> inline std::string typeName<int>() {return "int";}
589 template <> inline std::string typeName<long>() {return "long";}
590
591 template <> inline std::string typeName<signed char>() {return "signed char";}
592 template <> inline std::string typeName<unsigned char>() {return "unsigned char";}
593 template <> inline std::string typeName<unsigned short>(){return "unsigned short";}
594 template <> inline std::string typeName<unsigned int>() {return "unsigned int";}
595 template <> inline std::string typeName<unsigned long>() {return "unsigned long";}
596
597#ifdef HAVE_LONGLONG
598 template <> inline std::string typeName<long long>() {return "long long";}
599 template <> inline std::string typeName<unsigned long long>() {return "unsigned long long";}
600#endif
601
602 template <> inline std::string typeName<float>() {return "float";}
603 template <> inline std::string typeName<double>() {return "double";}
604 template <> inline std::string typeName<long double>() {return "long double";}
605
606
607 template <> inline std::string typeName<std::string>() {return "std::string";}
608 template <> inline std::string typeName<std::wstring>() {return "std::wstring";}
610
611 // handle C++ new fixed width types
612#if __cplusplus>=201103L
613 template <> inline std::string typeName<char16_t>() {return "char16_t";}
614 template <> inline std::string typeName<char32_t>() {return "char32_t";}
615#endif
616
617 template <class F>
618 typename enable_if<is_function<F>,string>::T
619 inline typeName() {return "<function>";}
620
621 template <class F>
623 inline typeName() {return "<function>";}
624
625#if defined(__cplusplus) && __cplusplus>=201103L
626 template <class F> struct tn<std::function<F>>
627 {
628 static string name() {return "std::function<"+typeName<F>()+">";}
629 };
630#endif
631
632 template <class T> struct tn<T*>
633 {
634 static std::string name()
635 {return typeName<T>()+"*";}
636 };
637
638 template <class T> struct tn<T&>
639 {
640 static std::string name()
641 {return typeName<T>()+"&";}
642 };
643
644 template <class T> struct tn<shared_ptr<T> >
645 {
646 static std::string name()
647 {return "classdesc::shared_ptr<"+typeName<T>()+">";}
648 };
649
650#if defined(__cplusplus) && __cplusplus <= 201402
651#if defined(__GNUC__) && !defined(__ICC) && !defined(__clang__)
652#pragma GCC diagnostic push
653#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
654#endif
655 template <class T> struct tn<std::auto_ptr<T> >
656 {
657 static std::string name()
658 {return "auto_ptr<"+typeName<T>()+">";}
659 };
660#if defined(__GNUC__) && !defined(__ICC) && !defined(__clang__)
661#pragma GCC diagnostic pop
662#endif
663#endif
664
665#if defined(__cplusplus) && __cplusplus>=201103L
666 template <class T> struct tn<std::unique_ptr<T> >
667 {
668 static std::string name()
669 {return "std::unique_ptr<"+typeName<T>()+">";}
670 };
671
672 template <class T, std::size_t N> struct tn<std::array<T,N> >
673 {
674 static std::string name()
675 {return "std::array<"+typeName<T>()+","+std::to_string(N)+">";}
676 };
677 template <class T> struct tn<weak_ptr<T> >
678 {
679 static std::string name()
680 {return "std::weak_ptr<"+typeName<T>()+">";}
681 };
682#endif
683
684 template <class T,class A> struct tn<std::vector<T,A> >
685 {
686 static std::string name()
687 {return "std::vector<"+typeName<T>()+">";}
688 };
689
690 template <class T, class A> struct tn<std::list<T,A> >
691 {
692 static std::string name()
693 {return "std::list<"+typeName<T>()+">";}
694 };
695
696 template <class T,class A> struct tn<std::deque<T,A> >
697 {
698 static std::string name()
699 {return "std::deque<"+typeName<T>()+">";}
700 };
701
702 template <class T, class C, class A> struct tn<std::set<T,C,A> >
703 {
704 static std::string name()
705 {return "std::set<"+typeName<T>()+">";}
706 };
707
708 template <class K, class V, class C, class A> struct tn<std::map<K,V,C,A> >
709 {
710 static std::string name()
711 {return "std::map<"+typeName<K>()+","+typeName<V>()+">";}
712 };
713
714 template <class T, class C, class A> struct tn<std::multiset<T,C,A> >
715 {
716 static std::string name()
717 {return "std::multiset<"+typeName<T>()+">";}
718 };
719
720 template <class K, class V, class C, class A> struct tn<std::multimap<K,V,C,A> >
721 {
722 static std::string name()
723 {return "std::multimap<"+typeName<K>()+","+typeName<V>()+">";}
724 };
725
726 template <class K, class V> struct tn<std::pair<K,V> >
727 {
728 static std::string name()
729 {return "std::pair<"+typeName<K>()+","+typeName<V>()+">";}
730 };
731
732#if defined(__cplusplus) && __cplusplus>=201103L
733 template <class K, class H, class E, class A> struct tn<std::unordered_set<K,H,E,A> >
734 {
735 static std::string name()
736 {return "std::unordered_set<"+typeName<K>()+">";}
737 };
738 template <class K, class H, class E, class A> struct tn<std::unordered_multiset<K,H,E,A> >
739 {
740 static std::string name()
741 {return "std::unordered_multiset<"+typeName<K>()+">";}
742 };
743 template <class K, class V, class C, class A> struct tn<std::unordered_map<K,V,C,A> >
744 {
745 static std::string name()
746 {return "std::unordered_map<"+typeName<K>()+","+typeName<V>()+">";}
747 };
748 template <class K, class V, class C, class A> struct tn<std::unordered_multimap<K,V,C,A> >
749 {
750 static std::string name()
751 {return "std::unordered_multimap<"+typeName<K>()+","+typeName<V>()+">";}
752 };
753
754#endif
755
756
758 struct EnumKey
759 {
760 const char* name;
761 int value;
762 };
763
764 typedef std::map<std::string,int> SVMap;
765 typedef std::map<int,std::string> VSMap;
766
767 template <class T>
768 class EnumKeys
769 {
770 SVMap s2v;
771 VSMap v2s;
772 public:
773 EnumKeys(const EnumKey* data, int size)
774 {
775 for (const EnumKey *i=data; i<data+size; i++)
776 {
777 s2v[i->name]=i->value;
778 v2s[i->value]=i->name;
779 }
780 }
781 T operator()(std::string key) const {
782 SVMap::const_iterator i=s2v.find(key);
783 if (i!=s2v.end()) return T(i->second);
784 else return T(0);
785 }
786 std::string operator()(int val) const
787 {
788 VSMap::const_iterator i=v2s.find(val);
789 if (i!=v2s.end()) return i->second;
790 else return "";
791 }
792 std::string operator()(T val) const {return operator()(int(val));}
793
794 bool has(T val) const {return v2s.count(val);}
795 bool has(const std::string& s) const {return s2v.count(s);}
796
797 // use these to iterate of the enum's keys
798 size_t size() const {return v2s.size();}
799 typedef VSMap::const_iterator iterator;
800 iterator begin() const {return v2s.begin();}
801 iterator end() const {return v2s.end();}
802
803 typedef iterator It; // resolves a type ambiguity below
804 class Siterator: public It
805 {
806 public:
807 typedef string value_type;
808 typedef string* pointer;
809 typedef const string& reference;
810 Siterator() {}
811 Siterator(const It& i): It(i) {}
812 const string& operator*() const {return It::operator*().second;}
813 const string* operator->() const {return &It::operator*().second;}
814 };
815
816 Siterator sbegin() const {return begin();}
817 Siterator send() const {return end();}
818
819 class Viterator: public It
820 {
821 public:
822 typedef T value_type;
823 typedef T* pointer;
824 typedef const T& reference;
825 Viterator() {}
826 Viterator(const It& i): It(i) {}
827 T operator*() const {return T(It::operator*().first);}
828 };
829
830 Viterator vbegin() const {return begin();}
831 Viterator vend() const {return end();}
832 };
833
834 namespace {
835 template <class T>
836 struct enum_keysData
837 {
838 static EnumKey keysData[];
839 static EnumKeys<T> keys;
840 };
841
842 // handle const case
843 template <class T> struct enum_keysData<const T>: public enum_keysData<T> {};
844
845
846 template <class T> int enumKey(const std::string&);
847 template <class T> std::string enumKey(int);
848 }
849
850 template <class T> const EnumKeys<typename remove_const<T>::type>&
851 enum_keys() {return enum_keysData<T>::keys;}
852
853 template <class E>
854 typename enable_if<is_enum<E>, std::string>::T to_string(E e)
855 {return enum_keys<E>()(e);}
856
857 template <class T>
858 typename enable_if<is_enum<T>, std::ostream&>::T
859 operator<<(std::ostream& o, T x)
860 {return o<<to_string(x);}
861
866 template <class T> //T is an enum
867 class Enum_handle
868 {
869 public:
870 T& ref;
871 Enum_handle(T& arg): ref(arg) {}
872 operator std::string() const {
873 return enumKey<typename remove_const<T>::type>(static_cast<int>(ref));
874 }
875 Enum_handle(const Enum_handle& x): ref(x.ref) {}
876 operator int() const {return static_cast<int>(ref);}
877 const Enum_handle& operator=(T x) {ref=x; return *this;}
878 const Enum_handle& operator=(int x) {ref=T(x); return *this;}
879 const Enum_handle& operator=(const std::string& x)
880 {ref=T(enumKey<T>(x)); return *this;}
881 };
882
883 template <class T>
884 std::istream& operator>>(std::istream& i, Enum_handle<T>& x)
885 {
886 std::string temp;
887 i>>temp;
888 x=temp;
889 return i;
890 }
891
892 template <class T>
893 std::ostream& operator<<(std::ostream& o, Enum_handle<T> x)
894 {
895 o << static_cast<std::string>(x);
896 return o;
897 }
898
899 template <class T>
900 Enum_handle<T> enum_handle(T& x) {return Enum_handle<T>(x);}
901
902 template <class T> struct tn<Enum_handle<T> >
903 {
904 static std::string name()
905 {return "classdesc::Enum_handle<"+typeName<T>()+">";}
906 };
907
908 template <class T,int n> struct tn<T [n]>
909 {
910 static std::string name()
911 {
912 std::ostringstream os;
913 os << typeName<T>()<<"["<<n<<"]";
914 return os.str();
915 }
916 };
917
918
920 class is_array {};
921
924
927
929 class is_node {};
930 class is_treenode: public is_node {};
931 class is_graphnode: public is_node {};
932
933 // derive from this to create a null descriptor
934 template <class T>
936 {
937 void operator()(void *targ, const string& desc, T& arg) {}
938 };
939
940 // get last component of name
941 inline std::string tail(const string& x) {
942 std::string r(x);
943 std::string::size_type i=r.rfind('.');
944 return r.substr( i==std::string::npos? 0: i+1);
945 }
946
947 // get all but last component of name
948 inline std::string head(const string& x) {
949 std::string r(x);
950 std::string::size_type i=r.rfind('.');
951 return r.substr( 0, i==std::string::npos? std::string::npos: i);
952 }
953
955 template <class TT> struct NonConstKeyValueType
956 {typedef TT T;};
957
958 template <class K, class V> struct NonConstKeyValueType<std::pair<const K,V> >
959 {typedef std::pair<K,V> T;};
960
961
966 template <class T>
967 struct ExcludeClass: public T
968 {
969 ExcludeClass() {}
970 template <class U> explicit ExcludeClass(const U& x): T(x) {}
971#if __cplusplus>=201103L
972 template <class... U> explicit ExcludeClass(U... args): T(std::forward<U>(args)...) {}
973#endif
974 template <class U> const T& operator=(const U& x) {return T::operator=(x);}
975 // template <class U> operator const U&() const {return *static_cast<const U*>(static_cast<const T*>(this));}
976 template <class U> operator const U&() const {return *(const U*)this;}
977 // template <class U> operator U&() {return *static_cast<U*>(static_cast<T*>(this));}
978 template <class U> operator U&() {return *(U*)this;}
979 // other operators?
980
981 };
982
983 template <class T>
984 struct ExcludeFundamental
985 {
986 typedef T& RefType;
987 typedef const T& ConstRefType;
988 T val;
989 ExcludeFundamental() {}
990 template <class U> explicit ExcludeFundamental(const U& x): val(x) {}
991 template <class U> const T& operator=(const U& x) {return val=x;}
992 template <class U> operator U() const {return val;}
993 operator RefType () {return val;}
994 operator ConstRefType () const {return val;}
995 T operator+(const T& x) const {return val+x;}
996 T operator-(const T& x) const {return val-x;}
997 T operator*(const T& x) const {return val*x;}
998 T operator/(const T& x) const {return val/x;}
999 T operator%(const T& x) const {return mod(val,x);}
1000 T operator+=(const T& x) {return val+=x;}
1001 T operator-=(const T& x) {return val-=x;}
1002 T operator*=(const T& x) {return val*=x;}
1003 T operator/=(const T& x) {return val/=x;}
1004 T operator%=(const T& x) {val=mod(val,x); return val;}
1005 bool operator==(const T& x) const {return val==x;}
1006 bool operator==(const ExcludeFundamental<T>& x) const {return val==x.val;}
1007 template <class U> bool operator!=(U x) const {return !operator==(x);}
1008 };
1009
1010 template <class T> struct Exclude: public
1011 conditional<is_class<T>::value, ExcludeClass<T>, ExcludeFundamental<T> >::T
1012 {
1013 typedef typename conditional
1014 <is_class<T>::value, ExcludeClass<T>, ExcludeFundamental<T> >::T Super;
1015 Exclude() {}
1016#if __cplusplus>=201103L
1017 template <class... U> explicit Exclude(U... args): Super(std::forward<U>(args)...) {}
1018#endif
1019 template <class U> explicit Exclude(const U& x): Super(x) {}
1020 template <class U> const T& operator=(const U& x) {return Super::operator=(x);}
1021 };
1022
1023 template <class T>
1024 struct Exclude<T*>
1025 {
1026 T* val;
1027 Exclude(): val(NULL) {}
1028#if __cplusplus>=201103L
1029 Exclude(std::nullptr_t): val(nullptr) {}
1030 bool operator==(std::nullptr_t) const {return val==nullptr;}
1031#endif
1032 bool operator==(const T* x) const {return val==x;}
1033 bool operator==(const Exclude<T*>& x) const {return val==x.val;}
1034 template <class U> bool operator!=(U x) const {return !operator==(x);}
1035 template <class U> explicit Exclude(const U& x): val(x) {}
1036 template <class U> const T& operator=(U x) {return *(val=x);}
1037 template <class U> operator U() const {return val;}
1038 T& operator*() {return *val;}
1039 const T& operator*() const {return *val;}
1040 T* operator->() {return val;}
1041 const T* operator->() const {return val;}
1042 template <class U>
1044 operator+(U x) {return val+x;}
1045 template <class U>
1046 typename enable_if<is_integral<U>,const T*>::T
1047 operator+(U x) const {return val+x;}
1048 std::ptrdiff_t operator-(const T* x) const {return val-x;}
1049 };
1050
1051 template <class T, class U>
1053 operator+(U x, Exclude<T*> y)
1054 {return y+x;}
1055
1056 template <class T>
1057 std::ptrdiff_t operator-(const T* x, const Exclude<T*> y)
1058 {return x-static_cast<T*>(y);}
1059
1060 template <class T>
1061 std::ptrdiff_t operator-(T* x, const Exclude<T*> y)
1062 {return x-static_cast<T*>(y);}
1063
1064 template <class T, class U> T mod(T x, U y) {return x%y;}
1065 template <class U> float mod(float x, U y) {return std::fmod(x,y);}
1066 template <class U> double mod(double x, U y) {return std::fmod(x,y);}
1067
1068
1069 // handle fundamental types
1070 template <>
1071 struct Exclude<bool>
1072 {
1073 typedef bool& RefType;
1074 typedef const bool& ConstRefType;
1075 bool val;
1076 Exclude() {}
1077 template <class U> explicit Exclude(const U& x): val(x) {}
1078 template <class U> bool operator=(const U& x) {return val=x;}
1079 template <class U> operator U() const {return val;}
1080 operator RefType () {return val;}
1081 operator ConstRefType () const {return val;}
1082 bool operator&&(const bool& x) const {return val&&x;}
1083 bool operator||(const bool& x) const {return val||x;}
1084 bool operator&=(const bool& x) {return val=val&&x;}
1085 bool operator|=(const bool& x) {return val=val||x;}
1086 bool operator!() const {return !val;}
1087 };
1088
1089 template <class T> struct is_excluded: public false_type {};
1090 template <class T> struct is_excluded<Exclude<T> >: public true_type {};
1091 template <class T> struct is_excluded<const Exclude<T> >: public true_type {};
1092
1093
1095
1096 template <class T>
1097 struct tn<Exclude<T> >
1098 {
1099 static std::string name()
1100 {return "classdesc::Exclude<"+typeName<T>()+">";}
1101 };
1102
1104 template <class action_t>
1106 {
1107 template <class U>
1108 void operator()(action_t&,const string&,U&) {}
1109 template <class T>
1110 void type(action_t&,const string&) {}
1111 };
1112
1115
1116 template <class B>
1118 {
1119 template <class C>
1120 static B& cast(C& x) {return static_cast<B&>(x);}
1121 template <class C>
1122 static const B& cast(const C& x) {return static_cast<const B&>(x);}
1123 };
1124
1125
1127 template <class T> string basename()
1128 {
1129 string r(".base_"+typeName<T>());
1130 for (size_t i=1; i<r.size(); ++i)
1131 if (!isalnum(r[i])) r[i]='_';
1132 return r;
1133 }
1134
1137 {
1138 enum Type {boolean, int_number, float_number, string, array, object, null};
1139 };
1140
1141 template <> inline std::string typeName<RESTProcessType::Type >()
1142 {return "::classdesc::RESTProcessType::Type";}
1143 namespace {
1144 template <> EnumKey enum_keysData<RESTProcessType::Type >::keysData[]=
1145 {
1146 {"boolean",int(RESTProcessType::boolean)},
1147 {"int_number",int(RESTProcessType::int_number)},
1148 {"float_number",int(RESTProcessType::float_number)},
1149 {"string",int(RESTProcessType::string)},
1150 {"array",int(RESTProcessType::array)},
1151 {"object",int(RESTProcessType::object)},
1152 {"null",int(RESTProcessType::null)}
1153 };
1154 template <> EnumKeys<RESTProcessType::Type > enum_keysData<RESTProcessType::Type >::keys(enum_keysData<RESTProcessType::Type >::keysData,sizeof(enum_keysData<RESTProcessType::Type >::keysData)/sizeof(enum_keysData<RESTProcessType::Type >::keysData[0]));
1155 template <> int enumKey<RESTProcessType::Type >(const string& x){return int(enum_keysData<RESTProcessType::Type >::keys(x));}
1156 template <> string enumKey<RESTProcessType::Type >(int x){return enum_keysData<RESTProcessType::Type >::keys(x);}
1157 }
1158
1160 inline void log(const std::string& msg)
1161 {
1162#ifdef __EMSCRIPTEN__
1163 emscripten_console_log(msg.c_str());
1164#else
1165 std::cout<<msg<<std::endl;
1166#endif
1167 }
1168}
1169
1170
1171#if defined(__GNUC__) && !defined(__ICC)
1172#pragma GCC diagnostic pop
1173#endif
1174
1175#endif
Definition classdesc.h:805
Definition classdesc.h:820
Definition classdesc.h:769
Definition classdesc.h:868
Definition classdesc.h:920
Definition classdesc.h:923
Definition classdesc.h:926
Definition classdesc.h:931
Definition classdesc.h:929
Definition classdesc.h:930
MPIbuf manipulator to send the MPIbuf's contents to a remote process.
Definition classdescMP.h:38
Contains definitions related to classdesc functionality.
const T & keyOf(const T &x)
utility key extraction function for associative containers
Definition classdesc.h:526
std::string typeName< void >()
a string representation of the type
Definition classdesc.h:584
void log(const std::string &msg)
allow logging to console in an emscripten environment.
Definition classdesc.h:1160
string basename()
returns a valid identifier to append to the descriptor of a base class
Definition classdesc.h:1127
STL namespace.
Definition classdesc.h:420
Definition RESTProcess_epilogue.h:159
enum symbol handling
Definition classdesc.h:759
Definition classdesc.h:427
Definition classdesc.h:985
Definition classdesc.h:1012
helper for unpacking into map value_types
Definition classdesc.h:956
Definition classdesc.h:405
helper for constructing null descriptors
Definition classdesc.h:1106
Definition classdesc.h:423
types for RESTProcess and other embedding applications
Definition classdesc.h:1137
Definition classdesc.h:1118
Definition classdesc.h:936
Definition classdesc.h:274
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
Definition classdesc.h:505
Definition classdesc.h:478
Definition classdesc.h:461
Definition classdesc.h:490
Definition classdesc.h:492
determines if T is a standard associative container
Definition classdesc.h:321
determines if T is a container
Definition classdesc.h:358
has default constructor, and is copiable
Definition classdesc.h:523
Definition classdesc.h:1089
true_type if T is a std::pair
Definition classdesc.h:367
can a temporary of type T be constructed and passed to an argument
Definition classdesc.h:531
determines if T is a standard sequence container
Definition classdesc.h:302
type trait for the smart pointer concept
Definition classdesc.h:371
true_type if T is a StringKeyMap
Definition classdesc.h:364
determines if this is a string
Definition classdesc.h:313
Definition classdesc.h:382
Definition classdesc.h:571
transfer the constness property of T to U
Definition classdesc.h:431