For what I know, typeid(type) would return a type_info object, typeid(type).name()
would print the name of the type, the names are depend on compilers. I would
like to build a table by std::map<typeid(type).name(), std::function>.

My questions :
(1) : For what I know, the names of typeid(type).name() are not
always unique(most of the time it would be unique),
so it may not a perfect key for std::map.
what about typeid(type)?Thanks

(2) : If I have to use typeid(type) as the key, the best choice I could
think of is using the map of boost::fusion, what would you recommend?

(3) : In my case, we don't need to insert the key and value pairs frequently
but access the value frequently. What kind of containers would you
recommend for instead of std::map or fusion::map? It would be best
if that kind of containers already developed by boost

I would like to use boost::fusion::map rather than std::map, because I don't want to
change the behaviors of the legacy codes for now

Our codes looks like this

if(typeid(T1) == A && typeid(T2) == B) { //do some jobs}
else if(typeid(T1) == C && typeid(T2) == D) {//do some jobs}
//and so on

I would like to get rid of these if...else loop without changing the results
I would like to use boost::fusion to complete this task, although I am still studying boost::fusion

Meta state machine looks like an optional, but I have to go through boost::mpl and boost::fusion
before I could use it. Besides, it maybe too complicated for some tasks?

Thanks

Recommended Answers

All 8 Replies

1) typeid(type) does not return a unique object in all cases. You might want to combine (typeid(type).name(),instanceNumber) as a key.

2) typeid(type) is not unique

3) HashTable

Our codes are something like(ignored virtual destructor)

struct base
{
};

struct derived_A : public base
{
};

struct derived_B : public base
{
};

struct derived_C : public base
{
};

void tasks(base &temp)
{
  if( typeid(temp) == typeid(derived_B) ) { //do something }
 else if( typeid(temp) == typeid(derived_C) ) { //do something }
}

base, derived_A, B, C are generated by protocol buffer, do I have another choices
to check the type of the protocol buffer at the runtime without typeid?
Besides, this is not my codes, I am maintaining some legacy codes
I don't want to change the behavior or the hierarchies of the protocol buffer
before I know the whole structures
Thanks

maybe type_index is not a bad choice

std::unordered_map< std::type_index, std::function<void(base&)> > tasks;

	tasks[ typeid(derived_A) ] = []( base& ) { /*do something*/ };
	tasks[ typeid(derived_B) ] = []( base& ) { /*do something*/ };
	tasks[ typeid(derived_C) ] = []( base& ) { /*do something*/ };

	base& obj = /* whatever */;

Shouldn't you be using a virtual function instead of dispatching on type looked up at run-time?

The lifetime of the object returned by typeid() is guaranteed by the standard, so the following would work:

void foo( base& b ) { derived_A& a = dynamic_cast<derived_A&>(b) ; /* ... */  }
void bar( base& ) { /* ... */ }
void baz( base& ) { /* ... */ }

struct cmp_typeinfo
{
    bool operator() ( const std::type_info* a, const std::type_info* b ) const
    { return a->before(*b) ; }
};


void tasks( base& temp )
{
    static std::map< const std::type_info*, std::function< void( base& ) >,
                     cmp_typeinfo > dispatch_table =
    {
        { &typeid(derived_A), foo },
        { &typeid(derived_B), bar },
        { &typeid(derived_C), baz },
        // ...
    };

    dispatch_table[ &typeid(temp) ]( temp ) ;
}

Shouldn't you be using a virtual function instead of dispatching on type looked up at run-time?

Could you tell me how to do it?
for now, using std::map is the easiest way I could think of
If there are another option(no matter it is better or not)
I would be very happy, I think the most interesting of programming
is there are unlimited solutions waiting for us to choose and learn

class base, derived_A, derived_B and derived_C are generated by google protocol buffer
so I have no intent to change the source codes generated by it

ps :
we have another complicated states which describe by if...else
Since it is much more complicated, I am studying meta state machine
I hope it could help us simplify the codes in the future
I don't like to deal with whole bunch of if...else...else if

Assuming that base, derived_A, derived_B, derived_C are classes generated by the protocol buffer which we do not want to modify, something like this:

struct task
{
    virtual ~task() {}
    virtual void do_it() = 0 ;
};

struct A : derived_A, task { virtual void do_it() override { /* do it for derived_A */ } } ;

struct B : derived_B, task { virtual void do_it() override { /* do it for derived_B */ } } ;

struct C : derived_C, task { virtual void do_it() override { /* do it for derived_C */ } } ;

void tasks( base& temp ) { dynamic_cast<task&>(temp).do_it() ; }

Needless to say, instantiate objects of type A, B, C in place of derived_A, derived_B, derived_C


BTW, I hadn't seen this earlier at the time I made the earlier post:

> maybe type_index is not a bad choice

std::unordered_map< std::/*type_index*/type_info, std::function<void(base&)> > tasks;
 
	tasks[ typeid(derived_A) ] = []( base& ) { /*do something*/ };
	tasks[ typeid(derived_B) ] = []( base& ) { /*do something*/ };
	tasks[ typeid(derived_C) ] = []( base& ) { /*do something*/ };

This won't compile; std::type_info is not copyable or assignable

This won't compile; std::type_info is not copyable or assignable

type_index

is a wrapper of type_info
A new class of c++11, but I am not sure this code could work or not
since I don't know it very well
I would prefer type_info rather than type_index before I could make sure it is safe

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.