#ifndef BB_VARIANT_H #define BB_VARIANT_H #include "bbtypeinfo.h" struct bbVariant{ template static bbObject *toObject( T *p ){ return dynamic_cast( p ); } template static bbObject *toObject( T const& ){ bbRuntimeError( "Variant cast failed" ); return 0; } template static T castObject( bbObject *p,typename C::bb_object_type d=0 ){ return dynamic_cast( p ); } template static T castObject(...){ bbRuntimeError( "Variant cast failed" ); return {}; } struct RepBase{ int _refs=1; virtual ~RepBase(){ } virtual void gcMark(){ } virtual bbTypeInfo *getType(){ return &bbVoidTypeInfo::instance; } virtual bbObject *getObject(){ return 0; } virtual bbVariant invoke( bbArray params ){ bbRuntimeError( "Variant is not invokable" ); return {}; } }; template struct Rep : public RepBase{ T value; Rep( const T &value ):value( value ){ } virtual void gcMark(){ bbGCMark( value ); } virtual bbTypeInfo *getType(){ return bbGetType(); } virtual bbObject *getObject(){ return toObject( value ); } }; /* template struct FuncRep : public Rep>{ FuncRep( bbFunction func ):Rep>( func ){ } template R invoke( bbArray params,detail::seq ){ return this->value( params[I].get()... ); } virtual bbVariant invoke( bbArray params ){ return bbVariant{ invoke( params,detail::gen_seq{} ) }; } }; template struct FuncRep : public Rep>{ FuncRep( bbFunction func ):Rep>( func ){ } template void invoke( bbArray params,detail::seq ){ this->value( params[I].get()... ); } virtual bbVariant invoke( bbArray params ){ invoke( params,detail::gen_seq{} ); return {}; } }; */ static RepBase _null; RepBase *_rep; void retain()const{ ++_rep->_refs; } void release(){ if( !--_rep->_refs && _rep!=&_null ) delete _rep; } // ***** public ***** bbVariant():_rep( &_null ){ } bbVariant( const bbVariant &v ):_rep( v._rep ){ retain(); } template explicit bbVariant( const T &t ):_rep( new Rep( t ) ){ } template explicit bbVariant( const bbGCVar &t ):_rep( new Rep( t.get() ) ){ } /* template explicit bbVariant( bbFunction func ) : _rep( new FuncRep( func ) ){ } template explicit bbVariant( R(*func)(A...) ):_rep( new FuncRep( bbMakefunc( func ) ) ){ } */ ~bbVariant(){ release(); } bbVariant &operator=( const bbVariant &v ){ v.retain(); release(); _rep=v._rep; return *this; } bbTypeInfo *getType()const{ return _rep->getType(); } operator bool()const{ return _rep!=&_null; } template T get()const{ Rep *p=dynamic_cast*>( _rep ); if( p ) return p->value; // bbTypeInfo *type=bbGetType(); // if( type->kind=="Class" ){ bbObject *obj=_rep->getObject(); typedef typename detail::remove_pointer::type C; return castObject( obj ); // } bbRuntimeError( "Variant cast failed" ); return T{}; } }; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; extern template struct bbVariant::Rep; inline void bbGCMark( const bbVariant &v ){ v._rep->gcMark(); } inline int bbCompare( const bbVariant &x,const bbVariant &y ){ return y._rep>x._rep ? -1 : x._rep>y._rep; } #endif