bbvariant.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #ifndef BB_VARIANT_H
  2. #define BB_VARIANT_H
  3. #include "bbtypeinfo.h"
  4. struct bbVariant{
  5. template<class T,class R=typename T::bb_object_type> static bbObject *toObject( T *p ){
  6. return dynamic_cast<bbObject*>( p );
  7. }
  8. template<class T> static bbObject *toObject( T const& ){
  9. bbRuntimeError( "Variant cast failed" );
  10. return 0;
  11. }
  12. template<class T,class C> static T castObject( bbObject *p,typename C::bb_object_type d=0 ){
  13. return dynamic_cast<T>( p );
  14. }
  15. template<class T,class C> static T castObject(...){
  16. bbRuntimeError( "Variant cast failed" );
  17. return {};
  18. }
  19. struct RepBase{
  20. int _refs=1;
  21. virtual ~RepBase(){
  22. }
  23. virtual void gcMark(){
  24. }
  25. virtual bbTypeInfo *getType(){
  26. return &bbVoidTypeInfo::instance;
  27. }
  28. virtual bbObject *getObject(){
  29. return 0;
  30. }
  31. virtual bbVariant invoke( bbArray<bbVariant> params ){
  32. bbRuntimeError( "Variant is not invokable" );
  33. return {};
  34. }
  35. };
  36. template<class T> struct Rep : public RepBase{
  37. T value;
  38. Rep( const T &value ):value( value ){
  39. }
  40. virtual void gcMark(){
  41. bbGCMark( value );
  42. }
  43. virtual bbTypeInfo *getType(){
  44. return bbGetType<T>();
  45. }
  46. virtual bbObject *getObject(){
  47. return toObject( value );
  48. }
  49. };
  50. /*
  51. template<class R,class...A> struct FuncRep : public Rep<bbFunction<R(A...)>>{
  52. FuncRep( bbFunction<R(A...)> func ):Rep<bbFunction<R(A...)>>( func ){
  53. }
  54. template<int...I> R invoke( bbArray<bbVariant> params,detail::seq<I...> ){
  55. return this->value( params[I].get<A>()... );
  56. }
  57. virtual bbVariant invoke( bbArray<bbVariant> params ){
  58. return bbVariant{ invoke( params,detail::gen_seq<sizeof...(A)>{} ) };
  59. }
  60. };
  61. template<class...A> struct FuncRep<void,A...> : public Rep<bbFunction<void(A...)>>{
  62. FuncRep( bbFunction<void(A...)> func ):Rep<bbFunction<void(A...)>>( func ){
  63. }
  64. template<int...I> void invoke( bbArray<bbVariant> params,detail::seq<I...> ){
  65. this->value( params[I].get<A>()... );
  66. }
  67. virtual bbVariant invoke( bbArray<bbVariant> params ){
  68. invoke( params,detail::gen_seq<sizeof...(A)>{} );
  69. return {};
  70. }
  71. };
  72. */
  73. static RepBase _null;
  74. RepBase *_rep;
  75. void retain()const{
  76. ++_rep->_refs;
  77. }
  78. void release(){
  79. if( !--_rep->_refs && _rep!=&_null ) delete _rep;
  80. }
  81. // ***** public *****
  82. bbVariant():_rep( &_null ){
  83. }
  84. bbVariant( const bbVariant &v ):_rep( v._rep ){
  85. retain();
  86. }
  87. template<class T> explicit bbVariant( const T &t ):_rep( new Rep<T>( t ) ){
  88. }
  89. template<class T> explicit bbVariant( const bbGCVar<T> &t ):_rep( new Rep<T*>( t.get() ) ){
  90. }
  91. /*
  92. template<class R,class...A> explicit bbVariant( bbFunction<R(A...)> func ) : _rep( new FuncRep<R,A...>( func ) ){
  93. }
  94. template<class R,class...A> explicit bbVariant( R(*func)(A...) ):_rep( new FuncRep<R,A...>( bbMakefunc( func ) ) ){
  95. }
  96. */
  97. ~bbVariant(){
  98. release();
  99. }
  100. bbVariant &operator=( const bbVariant &v ){
  101. v.retain();
  102. release();
  103. _rep=v._rep;
  104. return *this;
  105. }
  106. bbTypeInfo *getType()const{
  107. return _rep->getType();
  108. }
  109. operator bool()const{
  110. return _rep!=&_null;
  111. }
  112. template<class T> T get()const{
  113. Rep<T> *p=dynamic_cast<Rep<T>*>( _rep );
  114. if( p ) return p->value;
  115. // bbTypeInfo *type=bbGetType<T>();
  116. // if( type->kind=="Class" ){
  117. bbObject *obj=_rep->getObject();
  118. typedef typename detail::remove_pointer<T>::type C;
  119. return castObject<T,C>( obj );
  120. // }
  121. bbRuntimeError( "Variant cast failed" );
  122. return T{};
  123. }
  124. };
  125. extern template struct bbVariant::Rep<bbBool>;
  126. extern template struct bbVariant::Rep<bbByte>;
  127. extern template struct bbVariant::Rep<bbUByte>;
  128. extern template struct bbVariant::Rep<bbShort>;
  129. extern template struct bbVariant::Rep<bbUShort>;
  130. extern template struct bbVariant::Rep<bbInt>;
  131. extern template struct bbVariant::Rep<bbUInt>;
  132. extern template struct bbVariant::Rep<bbLong>;
  133. extern template struct bbVariant::Rep<bbULong>;
  134. extern template struct bbVariant::Rep<bbFloat>;
  135. extern template struct bbVariant::Rep<bbDouble>;
  136. extern template struct bbVariant::Rep<bbString>;
  137. inline void bbGCMark( const bbVariant &v ){
  138. v._rep->gcMark();
  139. }
  140. inline int bbCompare( const bbVariant &x,const bbVariant &y ){
  141. return y._rep>x._rep ? -1 : x._rep>y._rep;
  142. }
  143. #endif