具有多种返回类型的函数

Uro*_*327 5 c++ c++11

我有两个枚举,它们基本上确定(在运行时)要做什么。“映射”看起来像

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)

问题是,abC,以及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: 我无法编辑类CACBCC。我也无法编辑 和 的类/返回x()类型y()。所有这些类型都来自外部库。

Yak*_*ont 6

您可以使用连续传递风格。

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>