#ifndef BOOST_STATECHART_DETAIL_RTTI_POLICY_HPP_INCLUDED #define BOOST_STATECHART_DETAIL_RTTI_POLICY_HPP_INCLUDED ////////////////////////////////////////////////////////////////////////////// // Copyright 2002-2008 Andreas Huber Doenni // Distributed under the Boost Software License, Version 1.0. (See accompany- // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ////////////////////////////////////////////////////////////////////////////// #include #include // BOOST_MSVC #include #include // std::type_info namespace boost { namespace statechart { namespace detail { ////////////////////////////////////////////////////////////////////////////// struct id_provider { const void * pCustomId_; #if defined( BOOST_ENABLE_ASSERT_HANDLER ) || !defined( NDEBUG ) const std::type_info * pCustomIdType_; #endif }; template< class MostDerived > struct id_holder { static id_provider idProvider_; }; template< class MostDerived > id_provider id_holder< MostDerived >::idProvider_; ////////////////////////////////////////////////////////////////////////////// struct rtti_policy { #ifdef BOOST_STATECHART_USE_NATIVE_RTTI class id_type { public: //////////////////////////////////////////////////////////////////////// explicit id_type( const std::type_info & id ) : id_( id ) {} bool operator==( id_type right ) const { return id_ == right.id_ != 0; } bool operator!=( id_type right ) const { return !( *this == right ); } bool operator<( id_type right ) const { return id_.before( right.id_ ) != 0; } bool operator>( id_type right ) const { return right < *this; } bool operator>=( id_type right ) const { return !( *this < right ); } bool operator<=( id_type right ) const { return !( right < *this ); } private: //////////////////////////////////////////////////////////////////////// const std::type_info & id_; }; typedef bool id_provider_type; // dummy #else typedef const void * id_type; typedef const id_provider * id_provider_type; #endif //////////////////////////////////////////////////////////////////////////// template< class Base > class rtti_base_type : public Base { public: //////////////////////////////////////////////////////////////////////// typedef rtti_policy::id_type id_type; id_type dynamic_type() const { #ifdef BOOST_STATECHART_USE_NATIVE_RTTI return id_type( typeid( *this ) ); #else return idProvider_; #endif } #ifndef BOOST_STATECHART_USE_NATIVE_RTTI template< typename CustomId > const CustomId * custom_dynamic_type_ptr() const { BOOST_ASSERT( ( idProvider_->pCustomId_ == 0 ) || ( *idProvider_->pCustomIdType_ == typeid( CustomId ) ) ); return static_cast< const CustomId * >( idProvider_->pCustomId_ ); } #endif protected: #ifdef BOOST_STATECHART_USE_NATIVE_RTTI rtti_base_type( id_provider_type ) {} //////////////////////////////////////////////////////////////////////// #if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT( 4 ) ) // We make the destructor virtual for GCC because with this compiler // there is currently no way to disable the "has virtual functions but // non-virtual destructor" warning on a class by class basis. Although // it can be done on the compiler command line with // -Wno-non-virtual-dtor, this is undesirable as this would also // suppress legitimate warnings for types that are not states. virtual ~rtti_base_type() {} #else ~rtti_base_type() {} #endif private: //////////////////////////////////////////////////////////////////////// // For typeid( *this ) to return a value that corresponds to the most- // derived type, we need to have a vptr. Since this type does not // contain any virtual functions we need to artificially declare one so. virtual void dummy() {} #else rtti_base_type( id_provider_type idProvider ) : idProvider_( idProvider ) { } ~rtti_base_type() {} private: //////////////////////////////////////////////////////////////////////// id_provider_type idProvider_; #endif }; //////////////////////////////////////////////////////////////////////////// template< class MostDerived, class Base > class rtti_derived_type : public Base { public: //////////////////////////////////////////////////////////////////////// static id_type static_type() { #ifdef BOOST_STATECHART_USE_NATIVE_RTTI return id_type( typeid( const MostDerived ) ); #else return &id_holder< MostDerived >::idProvider_; #endif } #ifndef BOOST_STATECHART_USE_NATIVE_RTTI template< class CustomId > static const CustomId * custom_static_type_ptr() { BOOST_ASSERT( ( id_holder< MostDerived >::idProvider_.pCustomId_ == 0 ) || ( *id_holder< MostDerived >::idProvider_.pCustomIdType_ == typeid( CustomId ) ) ); return static_cast< const CustomId * >( id_holder< MostDerived >::idProvider_.pCustomId_ ); } template< class CustomId > static void custom_static_type_ptr( const CustomId * pCustomId ) { #if defined( BOOST_ENABLE_ASSERT_HANDLER ) || !defined( NDEBUG ) id_holder< MostDerived >::idProvider_.pCustomIdType_ = &typeid( CustomId ); #endif id_holder< MostDerived >::idProvider_.pCustomId_ = pCustomId; } #endif protected: //////////////////////////////////////////////////////////////////////// ~rtti_derived_type() {} #ifdef BOOST_STATECHART_USE_NATIVE_RTTI rtti_derived_type() : Base( false ) {} #else rtti_derived_type() : Base( &id_holder< MostDerived >::idProvider_ ) {} #endif }; }; } // namespace detail } // namespace statechart } // namespace boost #endif