How do I iterate over a type list and call a function? MPL? I have a base class BASE that has several subclasses A, B, C that have special capabilities, but no way to identify those capabilities aside from the type. I would like to determine if an object of type BASE is also of one of the special subclasses: ie void f( BASE* base) { if ( dynamic_cast< A* >( base ) != NULL ) { some_function( dynamic_cast< A* >( base ) ); } else if ( dynamic_cast< B* >( base ) != NULL ) { some_function( dynamic_cast< B* >( base ) ); } else if ( dynamic_cast< C* >( base ) != NULL ) { some_function( dynamic_cast< C* >( base ) ); } } I think you can see why I'd like a type list iterator solution to this. I have arranged for the some_function to be a template as well to make things easier. What I am looking for is the equivalent of find_if() but for types and done at run time. I looked over MPL, but MPL seems to apply at compile time without a door to the run time world. :-) Thanks for your helpful tips! ...Duane
Duane Murphy writes:
How do I iterate over a type list and call a function? MPL?
I have a base class BASE that has several subclasses A, B, C that have special capabilities, but no way to identify those capabilities aside from the type.
I would like to determine if an object of type BASE is also of one of the special subclasses:
ie void f( BASE* base) { if ( dynamic_cast< A* >( base ) != NULL ) { some_function( dynamic_cast< A* >( base ) ); } else if ( dynamic_cast< B* >( base ) != NULL ) { some_function( dynamic_cast< B* >( base ) ); } else if ( dynamic_cast< C* >( base ) != NULL ) { some_function( dynamic_cast< C* >( base ) ); } }
I think you can see why I'd like a type list iterator solution to this.
Try this: struct do_something { do_something( BASE* base ) : m_base( base ) {} template< typename T > void operator()( mpl::identity<T> ) const { if ( T* x = dynamic_cast< T* >( this->m_base ) ) some_function( x ); } BASE* m_base; }; mpl::for_each< mpl::vector , mpl::make_identity<_1> >( do_something( base ) );
I have arranged for the some_function to be a template as well to make things easier.
What I am looking for is the equivalent of find_if() but for types and done at run time. I looked over MPL, but MPL seems to apply at compile time without a door to the run time world. :-)
Not true :), but 'for_each' is indeed not documented at the moment. -- Aleksey Gurtovoy MetaCommunications Engineering
Aleksey Gurtovoy
I think you can see why I'd like a type list iterator solution to this.
Try this:
struct do_something { do_something( BASE* base ) : m_base( base ) {}
template< typename T > void operator()( mpl::identity<T> ) const { if ( T* x = dynamic_cast< T* >( this->m_base ) ) some_function( x ); }
BASE* m_base; };
mpl::for_each< mpl::vector , mpl::make_identity<_1> >( do_something( base ) );
In this case you test for all the derived types, even if you match the first one, so it's not identical. It would probably be nice of us to create a for_each_if() or until() function that stops when the function object returns true. I'm pretty sure I've needed something like that before... Oh yeah, the FSM example could probably benefit from it! A lot! -- Dave Abrahams Boost Consulting www.boost-consulting.com
David Abrahams writes:
Aleksey Gurtovoy
writes: I think you can see why I'd like a type list iterator solution to this.
Try this:
struct do_something { do_something( BASE* base ) : m_base( base ) {}
template< typename T > void operator()( mpl::identity<T> ) const { if ( T* x = dynamic_cast< T* >( this->m_base ) ) some_function( x ); }
BASE* m_base; };
mpl::for_each< mpl::vector , mpl::make_identity<_1> >( do_something( base ) );
In this case you test for all the derived types, even if you match the first one, so it's not identical.
Yes, I should have mentioned it. You can always throw an exception after finding the match, but...
It would probably be nice of us to create a for_each_if() or until() function that stops when the function object returns true.
... I agree. -- Aleksey Gurtovoy MetaCommunications Engineering
--- At Wed, 5 Oct 2005 09:50:54 -0400, David Abrahams wrote:
Aleksey Gurtovoy
writes: I think you can see why I'd like a type list iterator solution to this.
Try this:
struct do_something { do_something( BASE* base ) : m_base( base ) {}
template< typename T > void operator()( mpl::identity<T> ) const { if ( T* x = dynamic_cast< T* >( this->m_base ) ) some_function( x ); }
BASE* m_base; };
mpl::for_each< mpl::vector , mpl::make_identity<_1> >( do_something( base ) );
In this case you test for all the derived types, even if you match the first one, so it's not identical. It would probably be nice of us to create a for_each_if() or until() function that stops when the function object returns true. I'm pretty sure I've needed something like that before... Oh yeah, the FSM example could probably benefit from it! A lot!
Thanks for this solution Aleksey! This works great. I also used your
suggestion to throw an exception to unwind when the right type was
found. (Throwing an exception is not my favorite solution, but functional.)
David, I'm only working with the boost documentation; I don't have the
book, so I could not understand your suggestion using fold<>. It didn't
seem to match the template.
typedef fold
"Duane Murphy"
David, I'm only working with the boost documentation; I don't have the book, so I could not understand your suggestion using fold<>. It didn't seem to match the template.
typedef fold
::type t;
Uh, yeah, I got the argument order wrong. Exchange the last two, please.
I further didn't understand the NextFunctionType argument. Maybe the book would make this more clear. :-)
try_derived_class and do_nothing are "function object types." The algorithm tries each derived class in sequence by calling a specialization of try_derived_class for that class, and then calls do_nothing when it runs out of types. NextFunctionType is, well, the next function type to invoke on the pointer in case this dynamic cast fails. -- Dave Abrahams Boost Consulting www.boost-consulting.com
Duane Murphy writes:
Not having documentation for for_each makes it difficult to use. ;-)
Until we fix it, you can refer to chapter 4, "Code generation facilities" of http://www.boost.org/libs/mpl/doc/paper/mpl_paper.pdf
All of the documentation that I found, talks about meta-functions. for_each () seems to be a real function.
It is...
This is quite useful to understand. What other real functions are undocumented?
... and it's the only one so far. -- Aleksey Gurtovoy MetaCommunications Engineering
"Duane Murphy"
How do I iterate over a type list and call a function? MPL?
I have a base class BASE that has several subclasses A, B, C that have special capabilities, but no way to identify those capabilities aside from the type.
I would like to determine if an object of type BASE is also of one of the special subclasses:
ie void f( BASE* base) { if ( dynamic_cast< A* >( base ) != NULL ) { some_function( dynamic_cast< A* >( base ) ); } else if ( dynamic_cast< B* >( base ) != NULL ) { some_function( dynamic_cast< B* >( base ) ); } else if ( dynamic_cast< C* >( base ) != NULL ) { some_function( dynamic_cast< C* >( base ) ); } }
I think you can see why I'd like a type list iterator solution to this.
I have arranged for the some_function to be a template as well to make things easier.
What I am looking for is the equivalent of find_if() but for types and done at run time. I looked over MPL, but MPL seems to apply at compile time without a door to the run time world. :-)
If you read the chapter 11 of C++ Template Metaprogramming
(http://boost-consulting.com/mplbook/#table-of-contents-and-sample-chapters),
you'll learn about the approach for doing this. Something like:
struct do_nothing
{
void operator()() const {};
}
template
dispatch;
Now dispatch is a function object that does your thing. -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (3)
-
Aleksey Gurtovoy
-
David Abrahams
-
Duane Murphy