|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2003-01-12 10:39:15
Toon Knapen <toon.knapen_at_[hidden]> writes:
> I've been looking through some real code to see where we pactically could
> benefit from MPL and think I've found a nice one :
>
> If one wants to integrate generic programming inside a strong OO designed
> program, you might want to try to downcast a pointer to a base-class to all
> possible derived-classes and once you found the right derived class (and got
> all the type information you need again) you can restart using templates and
> a real generic approach. However to do this 'trick ' in a scalable manner,
> you need to try all downcasts based on a compile-time list of all derived
> classes instead of hardcoding the list like :
>
> downcast(base_class* base) {
> derived1 d1 = dynamic_cast< derived1* >( base ) ;
> if ( d1 ) foo< derived1 >( d1 ) ;
>
> derived2 d2 = dynamic_cast< derived2* >( base ) ;
> if ( d2 ) foo< derived2 >( d2 ) ;
> }
>
> This might seem like bad design but is a very helpfull construct to avoid
> performance penalties from a to much OO oriented approach by implementing
> performance critical pieces using generic programming. Therefor I think it
> can appeal to many people that are coming from OO and start looking at
> generic programming.
Hmm, I wouldn't do it that way, though.
template <class Base>
struct dispatch_table
: std::map<boost::python::type_info, void(*)(Base*)> {};
dispatch_table<base_class> dispatch;
dispatch[typeid(*base)](base); // invocation
would form the core of my solution.
Then I would add:
template <class Base, class Operator>
struct registrar
{
registrar(dispatch_table<Base>& table)
: table(table)
{}
template <class Derived>
void operator()(Derived*)
{
table[typeid(Derived)] = &normalize<Derived>::execute;
}
private:
template <class Derived>
struct normalize
{
typedef typename Operator::apply<Derived> derived_op;
static void execute(Base* base)
{
derived_op::execute(dynamic_cast<Derived*>(base));
};
};
dispatch_table<Base>& table;
};
And finally:
struct do_foo
{
template <class Derived>
struct apply
{
void execute(Derived* p) { foo<Derived>(p); }
};
};
mpl::for_each< list<leaf1,leaf2,leaf3>, add_pointer<mpl::_> >(
registrar<base_class,do_foo>(dispatch)
);
Something like this might make a nice introductory example.
-- David Abrahams dave_at_[hidden] * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk