I am reading the type of an object from a file:
enum class type_index { ... };
type_index typeidx = read(file_handle, type_index{});
Depending
I think your existing solution isn't bad. At the point of // do generic stuff
instead call into other functions overloaded on type
boost::fusion::for_each(possible_types, [&](auto i) {
if (i::typeidx != typeidx) { return; }
doSpecificStuff(i);
});
void doSpecificStuff(const TypeA& a) { ... }
void doSpecificStuff(const TypeB& b) { ... }
...
AFAIK you can't quite get a switch
, which is a little bit faster than the if...else
structure here, but not substantially and is unlikely to be noticeable for a process you run while reading a file.
Other options are all similar to this. Fusion or mpl random access containers or even std::tuple can be access with get<> but that requires a compile time index so you're building the cases up and still going through the indices with something like
if (idx == 0) { doSpecificStuff(std::get<0>(possible_types)); }
else if (idx == 1) ...
....
Which could be done with recursive templates, like:
template
void dispatchImpl(size_t idx)
{
if (idx >= std::tuple_size::value) return;
if (idx == current)
{
doSpecificStuff(std::get(possible_types));
return;
}
dispatchImpl(idx);
}
void dispatch(size_t idx) { dispatchImpl<0>(idx); }
The only alternative I'm aware of would be building an array of function pointers. See Optimal way to access std::tuple element in runtime by index. I don't think you really gain anything with that solution for your case and it's harder to follow.
One advantage to your fusion::for_each
solution is that it doesn't force your type indices to be continuous. As your application evolves you can add new types or remove old types easily and the code still works, which would be harder if you were trying to use the container index as your type index.