Reimplement the switchCases() hybrid implementation using array lookup
Summary
Reimplement the function Hybrid::switchCases(Range r,Index i,Function f)
that calls the function f
with an integral-constant that has the same value as the (possibly) runtime index i
if the range is a static-range and with a runtime index if it is a dynamic-range.
Details
Instead of tail-recursion as in the old implementation it is implemented as kind-of an automatically generated lookup-table and thus does not need a recursion-break condition.
It is also hybrid in two senses:
- if the range is static, call the function with an integral constant, otherwise with a runtime index
- if the index is a runtime index, perform a lookup to call the function with the corresponding integral constant, otherwise if it is already an integral constant, pass it directly to the function.
Examples
Zero-based vectors that can be indexed by integral constants only:
auto t = Dune::makeTupleVector(std::string("1"), 2, 3.0f);
Hybrid::switchCases<decltype(t)::size()>(1, [&t](auto ii) { t[ii] = 20; });
Using different ranges with different access:
auto t = Dune::makeTupleVector(std::string("1"), 2, 3.0f);
auto v = std::vector<double>{1.0, 2.0, 3.0};
// StaticIntegralRange
Hybrid::switchCases(range(Hybrid::size(t)), 1, [&t](auto ii) { t[ii] = 20; });
// IntegralRange
Hybrid::switchCases(range(Hybrid::size(v)), 1, [&v](auto ii) { t[ii] = 20.0; });
Accessing a tuple by lookup or by direct index access:
auto t = Dune::makeTupleVector(std::string("1"), 2, 3.0f);
auto index_seq = std::make_index_sequence<decltype(t)::size()>{};
// search for index 1 in index sequence
Hybrid::switchCases(index_seq, 1, [&t](auto ii) { t[ii] = 20; });
// call function directly
Hybrid::switchCases(index_seq, index_constant<1>{}, [&t](auto ii) { t[ii] = 20; });
Notes
Since all the code in the dune core/staging modules that use Hybrid::switchCases
essentially are restricted to simple index
lookup, all can be replaced by the new implementation. The advantage is that we do not need to provide a fallback implementation in case the index is out of range. This is necessary for the old switchCases
implementation in case a value should be returned.