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 would say the best thing would just be to use an array of functions that do what you want to do:
typedef std::tuple PossibleTypes;
typedef std::function Callback;
PossibleTypes possible_types;
std::array::value> callbacks = {
[&]{ doSomethingWith(std::get<0>(possible_types)); },
[&]{ doSomethingElseWith(std::get<1>(possible_types)); },
...
};
That array is easy to generate with the help of integer_sequence, if all your calls are really the same:
template
std::array makeCallbacksImpl(std::tuple& t,
integer_sequence)
{
return { [&]{ doSomethingWith(std::get(t)) }... };
// or maybe if you want doSomethingWith<4>(std::get<4>(t)):
// return { [&]{ doSomethingWith(std::get(t)) }... };
}
template
std::array makeCallbacks(std::tuple& t) {
return makeCallbacksImpl(t, make_integer_sequence{});
}
And once we have our array, regardless of which way we generate, we just need to call it:
void genericStuffWithIdx(int idx) {
if (idx >= 0 && idx < callbacks.size()) {
callbacks[idx]();
}
else {
// some error handler
}
}
Or if throwing is good enough:
void genericStuffWithIdx(int idx) {
callbacks.at(idx)(); // could throw std::out_of_range
}
You can't really beat array lookup on performance, although you do have indirection through std::function
. This will definitely beat the fusion for_each solution, since there even if idx == 0
, you're actually running through each element anyway. You would really want to use any()
in that case, so you can quit early. But still faster to just use an array.