|
Boost : |
From: Dylan Cuthbert (dylan_at_[hidden])
Date: 2002-09-08 21:11:41
You could use partial specialization ala MPL/Loki to switch between using
your type-specific efficient code and a generic any implementation.
Here's something I knocked up a few months ago to hide driver/platform
dependent data but still allow the data to be passed around "higher up" in
the interface.
The union "simple_type" contains the supported types - should probably use
"variant" so complex types (with constructors) can be held - either Andrei's
version or the boost version. Anyway, the code shows how you can switch the
internal representation depending on its type.
This uses the Loki type manipulator classes:
#include <loki/TypeManip.h>
#include <loki/Typelist.h>
#include <boost/any.hpp>
namspace impl
{
/*---------------------------------------------------*/
/*! blind Data encapsulation for platform specific
* drivers
*
* \author Dylan Cuthbert
* \date 2002/04/30
*//*-------------------------------------------------*/
class Data
{
public:
struct twoshorts_t
{
short value[2];
};
struct fourchars_t
{
char value[4];
};
typedef int int_t;
typedef unsigned int uint_t;
typedef float float_t;
private:
typedef boost::any complex_type;
union simple_type
{
int_t _value_i;
uint_t _value_ui;
float_t _value_f;
twoshorts_t _value_2s;
fourchars_t _value_4c;
//! overloaded functions for returning of data types
float_t& getImplData( Loki::Type2Type< float_t > ) { return
_value_f; }
int_t& getImplData( Loki::Type2Type< int_t > ) { return
_value_i; }
uint_t& getImplData( Loki::Type2Type< uint_t > ) { return
_value_ui; }
twoshorts_t& getImplData( Loki::Type2Type< twoshorts_t > ) { return
_value_2s; }
fourchars_t& getImplData( Loki::Type2Type< fourchars_t > ) { return
_value_4c; }
//! const overloaded functions for returning of data types
const float_t& getImplData( Loki::Type2Type< float_t > ) const
{ return _value_f; }
const int_t& getImplData( Loki::Type2Type< int_t > ) const
{ return _value_i; }
const uint_t& getImplData( Loki::Type2Type< uint_t > ) const
{ return _value_ui; }
const twoshorts_t& getImplData( Loki::Type2Type< twoshorts_t > ) const
{ return _value_2s; }
const fourchars_t& getImplData( Loki::Type2Type< fourchars_t > ) const
{ return _value_4c; }
simple_type() : _value_ui( 0 ) { }
};
//! the actual data
simple_type _simple;
complex_type _complex; // if complex data is needed it is stored here
template< class T >
class Access
{
public:
static const bool COMPLEX = ( Loki::TL::IndexOf< TYPELIST_5( int_t,
uint_t, float_t, twoshorts_t, fourchars_t ), T >::value == -1 );
struct Complex
{
private:
static inline void force_set( Data& _D )
{
_D._complex = T();
}
static inline bool check_empty( Data& _D )
{
return ( _D._complex.empty() || _D._complex.type() != typeid( T ) );
}
public:
static T& GetImplData( Data& _D )
{
if ( check_empty( _D ) ) force_set( _D );
return *boost::any_cast< T >( &_D._complex );
}
static const T& GetImplData_const( const Data& _D )
{
if ( check_empty( _D ) ) return T();
return *boost::any_cast< const T >( &_D );
}
static void SetImplData( Data& _D, const T& _Value )
{
_D._complex = _Value;
}
};
struct Simple
{
static T& GetImplData( Data& _D )
{
return _D._simple.getImplData( typename Loki::Type2Type< T >() );
}
static const T& GetImplData_const( const Data& _D )
{
return _D._simple.getImplData( typename Loki::Type2Type< T >() );
}
static void SetImplData( Data& _D, const T& _Data )
{
_D._simple.getImplData( typename Loki::Type2Type< T >() ) = _Data;
}
};
typedef typename Loki::Select< COMPLEX, Complex, Simple >::Result
Interface;
};
public:
Data() { }
template< class D >
Data( const D& _Data )
{
typename Access<D>::Interface::SetImplData( *this, _Data );
}
//! allow most forms of access
template< class D >
D& implData() // ????
{
return Access<D>::Interface::GetImplData( *this );
}
//! allow most forms of access
template< class D >
const D implData() const
{
return Access<D>::Interface::GetImplData_const( *this );
}
};
} // end namespace impl
-- --------------------------------- Q-Games, Dylan Cuthbert. http://www.q-games.com P2P internet radio - http://www.peercast.org "Geoff Leyland" <geoff.leyland_at_[hidden]> wrote in message news:1B405A46-C18E-11D6-B7E6-003065F9F514_at_epfl.ch... > On Vendredi, septembre 6, 2002, at 01:21 , "Dylan Cuthbert" > <dylan_at_[hidden]> wrote: > > > Looks like you've had a good play with it, I presume it supports any > > types > > now rather than the limited set you had before? > > Uh, no. :-( I've been waiting for boost 1.29 for a "new" any, and > following dynamic_any, which fixes one of the problems you mentioned > earlier. And, basically, I've been lazy. I've got quite a bit of code > that uses the .be<> or .ref<> syntax, and I thought I'd wait to see what > happened with any_cast<> and extract<> before I made the changes. Of > course, ideally, the contained type will be parameterised - but there'd > have to be matching syntax for the contained type from the object > returned by a > > wc_ptr ptr = a["one.two.three.four"]; > > ptr contains a pointer to a and the parsed path, but won't do anything > until you "use" it. This means that if a["one.two.three.four"] doesn't > exist, then > > ptr.be<int>(); will throw > ptr.exists(); will return false > and > ptr = 4.0; will build any necessary parts of the path in a (hopefully) > exception safe manner, ie, a won't be changed until we've build the > contained type and any intermediate containers, and if any building > fails, no memory will be leaked (hopefully). > > So if your contained type doesn't use be<>, but extract<>, you'd > probably want wc_ptr to have an extract rather than a be. > > There's a .guess() partly implemented, which contains those horrible > > template <class T> operator T() 's > > which might be an acceptable way of doing things - I really prefer > > std::map<std::string, vertex<real, vertex_less> >::size_type s = > a["the.map.size"].guess(); > > to > > std::map<string, vertex<std::real, vertex_less> >::size_type s = > a["the.map.size"].be<std::map<std::string, vertex<real, vertex_less> > >::size_type> > > (which is obviously a bit of a contrived example, but I get real ones > every day). > > anyway, have a look, and see what you think. It's definitely > (obviously?) a work in progress so any feedback (from anyone) would be > cool. > > cheers, > goof > > -- > The early bird catches the worm. > If you want something else for breakfast, get up later. > > Geoff Leyland, Village Idiot > Laboratoire d'energetique industrielle > LENI-DGM-EPFL, CH-1015, Lausanne, Switzerland > Phone: +41 (21) 693 3505, Fax: +41 (21) 693 35 02 > > _______________________________________________ > Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost >
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk