I have two enums which basically determine (on runtime) what to do. The 'mapping' looks something like
struct Foo { class CA; class CB; class CC; CA a; CB b; CC c; };
enum Base { A, B, C };
enum Func { X, Y };
Foo foo;
// A, X => use(foo.a.x());
// A, Y => use(foo.a.y());
// B, X => use(foo.b.x());
// B, Y => use(foo.b.y());
The problem is, that a
, b
and C
, as well as the return types of x()
and y()
are all of different types (some really huge template types).
Mapping the two enums using switches or ifs is pretty ugly and requires lots of effort so I wondered, if I could somehow write something like this:
struct Foo { class CA; class CB; class CC; CA a; CB b; CC c; };
enum Base { A, B, C, };
enum Func { X, Y, };
template <typename T> auto applyFunc(Func f, T t)
{
switch(f)
{
case X: return t.x();
case Y: return t.y();
}
}
auto getBase(Base b, Foo f)
{
switch(b)
{
case A: return f.a;
case B: return f.b;
case C: return f.c;
}
}
Func f;
Base b;
Foo foo;
use(applyFunc(f, getBase(b, foo)));
Edit 1:
I can not edit the classes CA
, CB
and CC
. I also can not edit the classes/return types of x()
and y()
. All those types come from an external library.
You can use continuation passing style.
template <class F> void applyFunc(WhichFunc w, T t, F f)
{
switch(w)
{
case X: f(t.x());
case Y: f(t.y());
}
}
template<class F>
void getBase(Base b, Foo foo, F f)
{
switch(b)
{
case A: f(foo.a);
case B: f(foo.b);
case C: f(foo.c);
}
}
Where instead of returning, you pass the next step as a parameter to the previous.
Func f;
Base b;
Foo foo;
getBase(b, [&](auto&&b){ applyFunc( f, b, [&](auto&& r){ use(r); } ); } );
or somesuch (there may be typos).
std::variant
(or boost) can be used to move the continuation until after the return value.
auto b = getBase(b);
auto r = visit( b, [&](auto&& b){ return applyFunc( f, b ); } );
visit( r, [](auto&& r){ use(r); } );
where instead of taking a continuation, each of the above returns a variant<possible_return_types_go_here>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With