我有两个枚举,它们基本上确定(在运行时)要做什么。“映射”看起来像
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());
Run Code Online (Sandbox Code Playgroud)
问题是,a、b和C,以及x()和的返回类型y()都是不同的类型(一些非常巨大的模板类型)。
使用开关或 ifs 映射两个枚举非常难看,并且需要付出很多努力,所以我想知道我是否可以以某种方式编写如下内容:
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)));
Run Code Online (Sandbox Code Playgroud)
编辑1:
我无法编辑类CA、CB和CC。我也无法编辑 和 的类/返回x()类型y()。所有这些类型都来自外部库。
您可以使用连续传递风格。
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);
}
}
Run Code Online (Sandbox Code Playgroud)
您不是返回,而是将下一步作为参数传递给上一步。
Func f;
Base b;
Foo foo;
getBase(b, [&](auto&&b){ applyFunc( f, b, [&](auto&& r){ use(r); } ); } );
Run Code Online (Sandbox Code Playgroud)
或类似的东西(可能有错别字)。
std::variant(或 boost)可用于将延续移动到返回值之后。
auto b = getBase(b);
auto r = visit( b, [&](auto&& b){ return applyFunc( f, b ); } );
visit( r, [](auto&& r){ use(r); } );
Run Code Online (Sandbox Code Playgroud)
其中,上面的每个都返回 a ,而不是采用延续variant<possible_return_types_go_here>。