Classdesc 3.44
unpack_base.h
Go to the documentation of this file.
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
12
13#ifndef CLASSDESC_PACK_BASE_H
14#define CLASSDESC_PACK_BASE_H
15#include "classdesc.h"
16#include "function.h"
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <assert.h>
23#include <stdarg.h>
24#include <exception>
25#include <vector>
26#include <algorithm>
27#include <typeinfo>
28
29#include <Realloc.h>
30
31#ifdef _MSC_VER
32// stupid warning about unassignable objects
33#pragma warning(disable:4512)
34#endif
35
36namespace classdesc
37{
38 struct XDR;
39
40 class pack_error : public exception
41 {
42 string msg;
43 public:
44 pack_error(const char *s): msg("pack:") {msg+=s;}
45 virtual ~pack_error() throw() {}
46 virtual const char* what() const throw() {return msg.c_str();}
47 };
48
49#ifdef XDR_PACK
50 typedef bool (*xdr_filter)(XDR*,...);
51#endif
52
53 struct basic_type
54 {
55 void *val;
56 size_t size;
57#ifdef XDR_PACK
58 xdr_filter filter;
59#endif
60 };
61
62#ifdef XDR_PACK
63 template <class T> xdr_filter XDR_filter(const T&);
64#endif
65
66 template <class T>
67 struct Basic_Type: public basic_type
68 {
69 Basic_Type(const T& x){
70 val=(void*)&x; size=sizeof(x);
71
72#if defined(__GNUC__) && !defined(__ICC)
73#pragma GCC diagnostic push
74 // gcc is not clever enough to delve into xdr to know this is not uninitialised
75#pragma GCC diagnostic ignored "-Wuninitialized"
76#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
77#endif
78
79#ifdef XDR_PACK
80 filter=XDR_filter(x);
81#endif
82#if defined(__GNUC__) && !defined(__ICC)
83#pragma GCC diagnostic pop
84#endif
85 }
86 };
87
92
93 enum Ptr_flag {DEFAULT, GRAPH, TREE};
94
99
100 struct PtrStoreBase
101 {
102 int cnt;
103 PtrStoreBase(): cnt(0) {}
104 virtual ~PtrStoreBase() {};
105 virtual void *data()=0;
106 };
107
112 template <class T>
113 struct PtrStore: public PtrStoreBase
114 {
115 T d;
116 void* data() {return &d;}
117 };
118
123 class PtrStoreRef
124 {
125 PtrStoreBase *d;
126 public:
127 void* data() {return d->data();}
128 PtrStoreRef(PtrStoreBase *d=NULL): d(d) {}
129 PtrStoreRef(const PtrStoreRef& x): d(x.d) {d && d->cnt++;}
130 PtrStoreRef& operator=(const PtrStoreRef& x) {d=x.d; d && d->cnt++; return *this;}
131 ~PtrStoreRef() {if (d && d->cnt-- == 0) delete d;}
132 };
133
137 class pack_t
138 {
139#if __cplusplus < 201103L
140 pack_t operator=(const pack_t&){return *this;}
141 pack_t(const pack_t&){}
142#else
143 pack_t operator=(const pack_t&)=delete;
144 pack_t(const pack_t&)=delete;
145#endif
146 protected:
147 FILE *f;
148 void swap_base (pack_t& other){
149 std::swap(f,other.f);
150 std::swap(mode,other.mode);
151 std::swap(m_data,other.m_data);
152 std::swap(m_size,other.m_size);
153 std::swap(m_pos,other.m_pos);
154 std::swap(ptr_flag,other.ptr_flag);
155 std::swap(alloced,other.alloced);
156 }
157 enum mode_t {buf, readf, writef};
158 mode_t mode;
159 char *m_data;
160 size_t m_size;
161 size_t m_pos;
162 public:
163 // class notimplemented{};
164 // int xdr;
165 Ptr_flag ptr_flag;
166 unsigned recur_max;
167 std::vector<PtrStoreRef> alloced; //allocated data used for cleaning up
168 const char* data() const {return m_data;}
169 char* data() {return m_data;}
170 size_t size() const {return m_size;}
171 size_t pos() const {return m_pos;}
172 char* realloc(char* d, size_t s) {
173#ifdef Realloc
174 return (char*)Realloc(d,s);
175#else
176 return (char*)classdesc::realloc(d,s);
177#endif
178 }
179 void realloc(size_t s) {m_data=realloc(m_data,s);}
183 void resize(size_t s) {
184 realloc(s);
185 if (!m_data) throw std::bad_alloc();
186 m_size=s;
187 }
188
189 virtual void append(const basic_type& x)
190 {
191 if (mode==buf)
192 {
193 realloc(m_size+x.size);
194 if (!m_data)
195 throw std::bad_alloc();
196 memcpy(m_data+m_size,x.val,x.size);
197 }
198 else
199 if (fwrite(x.val,x.size,1,f) != 1)
200 throw pack_error("file write fail");
201 m_size+=x.size;
202 }
203 virtual void popoff(basic_type& x)
204 {
205 if (mode==buf)
206 if (m_pos+x.size>m_size)
207 throw pack_error("unexpected end of data");
208 else
209 memcpy(x.val,m_data+m_pos,x.size);
210 else
211 if (fread(x.val,x.size,1,f) != 1)
212 throw pack_error("unexpected end of file");
213 m_pos+=x.size;
214 }
215
216 pack_t(size_t sz=0): f(0), mode(buf), m_data(NULL), m_size(sz), m_pos(0), ptr_flag(DEFAULT), recur_max(500) {
217#ifdef RECUR_MAX
218 recur_max=RECUR_MAX;
219#endif
220 realloc(sz);}
221 pack_t(const char *fname, const char *rw):
222 f(fopen(fname,rw)), mode( (rw&&rw[0]=='w')? writef: readf),
223 m_data(0), m_size(0), m_pos(0), ptr_flag(DEFAULT), recur_max(500) {
224 // this is to support a deprecated interface
225#ifdef RECUR_MAX
226 recur_max=RECUR_MAX;
227#endif
228 if (!f) throw pack_error(strerror(errno));
229 }
230 virtual ~pack_t() {realloc(0); if (f) fclose(f);}
231
232#if __cplusplus >= 201103L
233 pack_t(pack_t&& x): f(nullptr), m_data(nullptr) {swap_base(x);}
234 pack_t& operator=(pack_t&& x) {swap_base(x); return *this;}
235#endif
236
237 operator bool() {return m_pos<m_size;}
238 virtual pack_t& reseti() {m_size=0; if (f) fseek(f,0,SEEK_SET); return *this;}
239 virtual pack_t& reseto() {m_pos=0; if (f) fseek(f,0,SEEK_SET); return *this;}
240 virtual pack_t& seeki(long offs) {
241 assert(offs<=0); m_size+=offs;
242 if (f) fseek(f,offs,SEEK_CUR);
243 return *this;
244 }
245 virtual pack_t& seeko(long offs) {
246 m_pos+=offs;
247 if (f) fseek(f,offs,SEEK_CUR);
248 return *this;
249 }
250 void clear() {realloc(0); m_data=0; m_size=m_pos=0;}
251 virtual void packraw(const char *x, size_t s)
252 {
253 if (mode==buf)
254 {
255 realloc(m_size+s);
256 memcpy(m_data+m_size,x,s); m_size+=s;
257 }
258 else
259 if (fwrite(x,s,1,f)!=1)
260 throw pack_error("filed to write data to stream");
261
262 }
263
264#if defined(__GNUC__) && !defined(__ICC)
265#pragma GCC diagnostic push
266 // this warning is randomly triggered on Tumbleweed docker environment
267#pragma GCC diagnostic ignored "-Warray-bounds"
268#endif
269 virtual void unpackraw(char *x, size_t s)
270 {
271 if (mode==buf)
272 {
273 if (s>m_size-m_pos)
274 throw pack_error("premature end of buffered data");
275 memcpy(x,m_data+m_pos,s);
276 }
277 else
278 if (fread(x,s,1,f)!=1)
279 throw pack_error("premature end of stream");
280 m_pos+=s;
281 }
282#if defined(__GNUC__) && !defined(__ICC)
283#pragma GCC diagnostic pop
284#endif
285
286 virtual void swap(pack_t& other) {
287 if (typeid(*this)!=typeid(other))
288 throw pack_error("cannot swap differing types");
289 swap_base(other);
290 }
293 virtual int cmp(const pack_t& x) const {
294 if (m_size==x.m_size)
295 return memcmp(m_data,x.m_data,m_size);
296 else
297 return m_size<x.m_size? -1: 1;
298 }
299
300 bool operator<(const pack_t& x) const {return cmp(x)==-1;}
301 bool operator>(const pack_t& x) const {return cmp(x)==1;}
302 bool operator==(const pack_t& x) const {return cmp(x)==0;}
303 bool operator!=(const pack_t& x) const {return cmp(x)!=0;}
304 };
305
307 template <class T>
308 int deepCmp(const T& x, const T& y) {
309 pack_t xb, yb;
310 return (xb<<x).cmp(yb<<y);
311 }
313 template <class T>
314 bool deepEq(const T& x, const T& y) {
315 pack_t xb, yb;
316 return (xb<<x).cmp(yb<<y)==0;
317 }
318
319 typedef pack_t unpack_t;
320
321 template <> inline string typeName<pack_t>() {return "classdesc::pack_t";}
322
323#ifdef XDR_PACK
324 const int BUFCHUNK=1024;
325
329 class xdr_pack: public pack_t
330 {
331 size_t asize;
332 XDR *input, *output;
333 public:
334 xdr_pack(size_t sz=BUFCHUNK);
335 xdr_pack(const char *, const char* rw);
336 ~xdr_pack();
337#if __cplusplus >= 201103L
338 xdr_pack(xdr_pack&& x): input(nullptr), output(nullptr) {swap(x);}
339 xdr_pack& operator=(xdr_pack&& x) {swap(x); return *this;}
340#endif
341
342 virtual void append(const basic_type& x);
343 virtual void popoff(basic_type& x);
344 virtual xdr_pack& reseti();
345 virtual xdr_pack& reseto();
346 virtual xdr_pack& seeki(long offs);
347 virtual xdr_pack& seeko(long offs);
348 virtual void packraw(const char *x, size_t sz);
349 virtual void unpackraw(char *x, size_t sz);
350 virtual void swap(pack_t& other) {
351 xdr_pack* xdr_other=dynamic_cast<xdr_pack*>(&other);
352 if (!xdr_other) throw pack_error("cannot swap differing types");
353 swap_base(other);
354 std::swap(asize,xdr_other->asize);
355 std::swap(input,xdr_other->input);
356 std::swap(input,xdr_other->output);
357 }
358 };
359 template <> inline string typeName<xdr_pack>() {return "classdesc::xdr_pack";}
360#else
361 typedef pack_t xdr_pack;
362#endif
363
370
371 class BinStream
372 {
373 pack_t& packer;
374 public:
375 BinStream(pack_t& packer): packer(packer) {}
376 template <class T>
377 typename enable_if<Not<is_container<T> >, BinStream&>::T
378 operator<<(const T& o)
379 {
380 packer.packraw(reinterpret_cast<const char*>(&o), sizeof(T));
381 return *this;
382 }
383 template <class T>
384 typename enable_if<Not<is_container<T> >, BinStream&>::T
385 operator>>(T& o)
386 {
387 packer.unpackraw(reinterpret_cast<char*>(&o), sizeof(T));
388 return *this;
389 }
390
391 template <class T>
392 typename enable_if<is_container<T>, BinStream&>::T
393 operator<<(const T& o)
394 {
395 (*this)<<o.size();
396 for (typename T::const_iterator i=o.begin(); i!=o.end(); ++i)
397 (*this)<<*i;
398 return *this;
399 }
400
401 template <class T>
402 typename enable_if<is_sequence<T>, BinStream&>::T
403 operator>>(T& o)
404 {
405 size_t s;
406 (*this)>>s;
407 typename T::value_type v;
408 for (size_t i=0; i<s; ++i)
409 {
410 (*this)>>v;
411 o.push_back(v);
412 }
413 return *this;
414 }
415
416 template <class T>
417 typename enable_if<is_associative_container<T>, BinStream&>::T
418 operator>>(T& o)
419 {
420 size_t s;
421 (*this)>>s;
422 typename T::value_type v;
423 for (size_t i=0; i<s; ++i)
424 {
425 (*this)>>v;
426 o.insert(v);
427 }
428 return *this;
429 }
430
432 template <class T, class A>
433 inline BinStream& operator<<(const std::vector<T,A>& o);
434
435 template <class T, class A>
436 inline BinStream& operator>>(std::vector<T,A>& o);
437
438 };
439
445 template <class Pack> struct BinStreamT: public BinStream
446 {
447 Pack thePack;
448 BinStreamT(): BinStream(thePack) {}
449 template <class A1> BinStreamT(A1 a1):
450 BinStream(thePack), thePack(a1) {}
451 template <class A1, class A2> BinStreamT(A1 a1, A2 a2):
452 BinStream(thePack), thePack(a1, a2) {}
453 };
454
455
465 template <class T>
466 struct unserialisable: public T
467 {
468 unserialisable() {}
469 unserialisable(const T& x): T(x) {}
470 unserialisable operator=(const T& x) {T::operator=(x); return *this;}
471 };
472
473
474 template <class T> pack_t& operator<<(pack_t& y,const T&x);
475 template <class T> pack_t& operator>>(pack_t& y,T&x);
476
479 template <class T> struct pack_supported:
480 public Or<
481 Or<
482 is_fundamental<T>,
483 is_container<T>
484 >,
485 is_excluded<T>
486 > {};
487
488#ifndef THROW_PTR_EXCEPTION
489 template <class T>
490 inline void pack(pack_t& targ, const string& desc, is_treenode dum, const T* const& arg);
491
492 template <class T>
493 inline void unpack(unpack_t& targ, const string& desc,
494 is_treenode dum, T*& arg);
495
496 template <class T>
497 inline void pack(pack_t& targ, const string& desc,
498 is_graphnode dum,const T& arg);
499
501
502 template <class T>
503 inline void unpack(pack_t& targ, const string& desc,
504 is_graphnode dum,T& arg);
505
506#endif
507
508 template <class T>
509 void pack_onbase(pack_t& x,const string& d,T& a)
510 {pack(x,d,a);}
511
512 template <class T>
513 void unpack_onbase(unpack_t& x,const string& d,T& a)
514 {unpack(x,d,a);}
515}
516
517using classdesc::pack_onbase;
518using classdesc::unpack_onbase;
519
524
525namespace classdesc_access
526{
528 template <class T> struct access_pack;
530 template <class T> struct access_unpack;
531
532 /* default action for pointers is to throw an error message */
533 template <class T>
534 struct access_pack<T*>
535 {
536 typedef T Arg;
537 template <class C>
539 operator()(classdesc::pack_t& targ, const classdesc::string& desc, C& arg)
540 {
541 switch (targ.ptr_flag)
542 {
543 // You may wish to define this macro if you have messy types containing pointers
544#ifndef THROW_PTR_EXCEPTION
545 case classdesc::GRAPH:
546 pack(targ,desc,classdesc::is_graphnode(),arg);
547 break;
548 case classdesc::TREE:
549 pack(targ,desc,classdesc::is_treenode(),arg);
550 break;
551#endif
552 default:
553 throw classdesc::pack_error("Packing arbitrary pointer data not implemented");
554 }
555 }
556 };
557
558 template <class T>
559 struct access_unpack<T*>
560 {
561 template <class C>
562 void operator()(classdesc::unpack_t& targ, const classdesc::string& desc, C& arg)
563 {
564 switch (targ.ptr_flag)
565 {
566 // You may wish to define this macro if you have messy types containing pointers
567#ifndef THROW_PTR_EXCEPTION
568 case classdesc::GRAPH:
569 unpack(targ,desc,classdesc::is_graphnode(),arg);
570 break;
571 case classdesc::TREE:
572 unpack(targ,desc,classdesc::is_treenode(),arg);
573 break;
574#endif
575 default:
576 throw classdesc::pack_error("Unpacking arbitrary pointer data not implemented");
577 }
578 }
579 };
580
581 template <class T>
582 struct access_pack<classdesc::unserialisable<T> >:
583 public classdesc::NullDescriptor<classdesc::pack_t> {};
584
585 template <class T>
586 struct access_unpack<classdesc::unserialisable<T> >:
587 public classdesc::NullDescriptor<classdesc::pack_t> {};
588
589 template <class T>
590 struct access_pack<classdesc::Exclude<T> >:
591 public classdesc::NullDescriptor<classdesc::pack_t> {};
592
593 template <class T>
594 struct access_unpack<classdesc::Exclude<T> >:
595 public classdesc::NullDescriptor<classdesc::pack_t> {};
596
597}
598
599namespace classdesc
600{
601 //generic pack, unpack - defined in pack_stream
602 template <class T> typename
604 pack(pack_t& buf, const string& desc, T& arg)
605 {classdesc_access::access_pack<T>()(buf,desc,arg);}
606
607
608 template <class T> typename
610 unpack(unpack_t& buf, const string& desc, T& arg)
611 {classdesc_access::access_unpack<T>()(buf,desc,arg);}
612
613 template <class T>
614 typename enable_if<is_fundamental<T>, void>::T
615 pack(pack_t& targ, const string&, T& arg)
616 {
617 Basic_Type<T> b(arg);
618 targ.append(b);
619 }
620
621 template <class T>
622 typename enable_if<is_fundamental<T>, void>::T
623 pack(pack_t& targ, const string&, const T& arg)
624 {
625 Basic_Type<T> b(arg);
626 targ.append(b);
627 }
628
629 template <class T>
630 typename enable_if<is_fundamental<T>, void>::T
631 unpack(unpack_t& targ, const string&, T& arg)
632 {
633 Basic_Type<T> b(arg);
634 targ.popoff(b);
635 }
636
637 template <class T>
638 typename enable_if<is_fundamental<T>, void>::T
639 unpack(unpack_t& targ, const string&, const T&)
640 { /* const vars cannot be unpacked */
641 T dum(0); Basic_Type<T> b(dum);
642 targ.popoff(b);
643 }
644
645
646 /* The problem is that function pointers this template also, so we
647 need a separate pack to packup pointers to single objects:
648
649 pack a flag indicating validity, and then the object pointer points
650 to. Cannot handle arrays, but useful for graphs - assumes pointer is
651 valid unless NULL.
652
653 */
654
655
656 template <class T>
657 void pack(pack_t& targ, const string& desc, is_array,
658 T &arg,int dims,size_t ncopies,...)
659 {
660 va_list ap;
661 va_start(ap,ncopies);
662 for (int i=1; i<dims; i++) ncopies*=va_arg(ap,int); //assume that 2 and higher D arrays dimensions are int
663 va_end(ap);
664 for (size_t i=0; i<ncopies; i++) pack(targ,desc,(&arg)[i]);
665 }
666
667 template <class T>
668 void unpack(unpack_t& targ, const string& desc, is_array, T &arg,
669 int dims,size_t ncopies,...)
670 {
671 va_list ap;
672 va_start(ap,ncopies);
673 for (int i=1; i<dims; i++) ncopies*=va_arg(ap,int);
674 va_end(ap);
675 for (size_t i=0; i<ncopies; i++) unpack(targ,desc,(&arg)[i]);
676 }
677
678 /* specialise for char* */
679 inline void pack(pack_t& targ, const string&, is_array,
680 char &arg,int dims,size_t ncopies,...)
681 {
682 int i;
683 va_list ap;
684 va_start(ap,ncopies);
685 for (i=1; i<dims; i++) ncopies*=va_arg(ap,int);
686 va_end(ap);
687 targ.packraw(&arg,ncopies);
688 }
689
690 inline void unpack(unpack_t& targ, const string&, is_array,
691 char &arg,int dims,size_t ncopies,...)
692 {
693 int i;
694 va_list ap;
695 va_start(ap,ncopies);
696 for (i=1; i<dims; i++) ncopies*=va_arg(ap,int);
697 va_end(ap);
698 targ.unpackraw(&arg,ncopies);
699 }
700
701 /*
702 Method pointer serialisation
703 */
704 template <class C, class R, class A1>
705 void pack(pack_t& targ, const string& desc, R (C::*&arg)(A1))
706 {targ.packraw((char*)&arg,sizeof(arg));}
707
708 template <class C, class R, class A1>
709 void unpack(pack_t& targ, const string& desc, R (C::*&arg)(A1))
710 {targ.unpackraw((char*)&arg,sizeof(arg));}
711
712 template<class C, class T>
715 pack(pack_t& b, const string& d, C& o, T y);
716 template<class C, class T>
719 unpack(unpack_t& b, const string& d, C& o, T y);
720
721 template<class C, class T>
722 typename enable_if<
724 is_object<T> >,void>::T
725 pack(pack_t& b, const string& d, C&, T* y);
726 template<class C, class T>
727 typename enable_if<
729 is_object<T> >,void>::T
730 unpack(unpack_t& b, const string& d, C&, T* y);
731
733 template <class T>
734 void pack(pack_t& targ, const string& desc, is_const_static i, T t)
735 {}
736
737 template <class T>
738 void unpack(pack_t& targ, const string& desc,is_const_static i, T t)
739 {}
740
741 // static methods
742 template <class T, class U>
743 void pack(pack_t&, const string&,is_const_static, const T&, U) {}
744
745 template <class T, class U>
746 void unpack(pack_t& targ, const string& desc,is_const_static i, const T&, U) {}
747
748 // to handle pack/unpacking of enums when -typeName is in effect
749 template <class E>
750 void pack(pack_t& targ, const string& desc,Enum_handle<E> a)
751 {
752 int x=a;
753 pack(targ,desc,x);
754 }
755
756 template <class E>
757 void unpack(pack_t& targ, const string& desc, Enum_handle<E> a)
758 {
759 int x;
760 unpack(targ,desc,x);
761 a=x;
762 }
763
764 template <class T> void pack(pack_t&, const string&, const Exclude<T>&) {}
765 template <class T> void unpack(pack_t&, const string&, const Exclude<T>&) {}
766
767}
768
769#include "use_mbr_pointers.h"
770CLASSDESC_FUNCTION_NOP(pack)
771CLASSDESC_FUNCTION_NOP(unpack)
772
773using classdesc::pack;
775using classdesc::pack_onbase;
776using classdesc::unpack_onbase;
777
778#ifdef _CLASSDESC
779#pragma omit pack classdesc::string
780#pragma omit pack eco_strstream
781#pragma omit pack xdr_pack
782#pragma omit unpack classdesc::string
783#pragma omit unpack eco_strstream
784#pragma omit unpack xdr_pack
785#endif
786#endif
Definition pack_base.h:372
BinStream & operator<<(const std::vector< T, A > &o)
specialisation for vector
Definition classdesc.h:868
Definition pack_base.h:124
Definition classdesc.h:920
Definition classdesc.h:923
Definition classdesc.h:931
Definition classdesc.h:930
Definition pack_base.h:41
Definition pack_base.h:138
size_t m_size
size of buffer
Definition pack_base.h:160
unsigned recur_max
recursion limit for pack_graph
Definition pack_base.h:166
size_t size() const
size of buffer
Definition unpack_base.h:170
char * data()
actual buffer
Definition unpack_base.h:169
char * m_data
actual buffer
Definition pack_base.h:159
size_t m_pos
position of read pointer
Definition pack_base.h:161
virtual int cmp(const pack_t &x) const
Definition unpack_base.h:293
size_t pos() const
position of read pointer
Definition unpack_base.h:171
const char * data() const
actual buffer
Definition unpack_base.h:168
void resize(size_t s)
Definition unpack_base.h:183
Definition pack_base.h:330
Metaprogramming support for processing functions of multiple arguments.
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
void pack(pack_t &targ, const string &desc, is_treenode dum, const T *const &arg)
serialise a tree (or DAG)
Definition pack_graph.h:28
void unpack(unpack_t &targ, const string &desc, is_treenode dum, T *&arg)
unserialise a tree.
Definition pack_graph.h:44
Ptr_flag
Definition pack_base.h:93
bool deepEq(const T &x, const T &y)
deep equality of two serialisable items
Definition pack_base.h:314
int deepCmp(const T &x, const T &y)
deep comparison of two serialisable items
Definition pack_base.h:308
Definition classdesc.h:420
Definition pack_base.h:68
Definition pack_base.h:446
Definition classdesc.h:1012
Definition classdesc.h:405
helper for constructing null descriptors
Definition classdesc.h:1106
Definition classdesc.h:423
Definition pack_base.h:101
Definition pack_base.h:114
Definition pack_base.h:54
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
base class for exceptions thrown by classdesc
Definition classdesc.h:546
Definition pack_base.h:486
Definition pack_base.h:467
class to allow access to private members
Definition classdesc_access.h:21
class to allow access to private members
Definition classdesc_access.h:22