#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 <boost/assert.hpp> | |
#include <boost/config.hpp> // BOOST_MSVC | |
#include <boost/detail/workaround.hpp> | |
#include <typeinfo> // 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 |