5

使用以下代码如何正确编写自定义模板推导?

template<class R, class State, class... Ts> struct visitor : Ts... { using  Ts::operator()...; };
template<class R, class State, class... Ts> visitor(State, Ts...)->visitor<class R, State,Ts...>;

using Event = std::variant<HeartBeat, ConfigurationRead>;
using State = std::variant<Idle, Starting, Running, Error>;

void case3()
{
    Event e;
    State currentState;
    State newState = std::visit( visitor{
        [](Idle&& state, HeartBeat event) {std::cout << "Currently stopped, heartbeat received.\n"; return Error{}; }
    }, currentState, e);
}

我查看了几个示例,但找不到使用 std::visit 返回的示例。

4

1 回答 1

7

您的访问者不需要推断和编码返回类型R- 将自行推断std::visit:从可调用或固定到指定的模板参数(见下文)。话虽如此,它可以简化为:

template <typename... Ts> struct visitor : Ts... { using Ts::operator()...; };
template <typename... Ts> visitor(Ts...) -> visitor<Ts...>;

但是,在中,每个访问者都必须返回相同的类型。您可以通过例如为每个 lambda 表达式显式指定一个来避免任何类型不匹配:

State newState = std::visit( visitor{
        [](Idle state, HeartBeat event) -> State { return Error{}; },
        //                                 ~~~~^
        [](auto state, auto event) -> State { return state; }
        //                            ~~~~^
    }, currentState, e);

演示


中,可以将返回类型指定为的第一个模板参数std::visit

State newState = std::visit<State>( visitor{
        //                  ~~~~^
        [](Idle state, HeartBeat event) { return Error{}; },
        [](auto state, auto event) { return state; }
    }, currentState, e);
于 2018-11-24T22:13:44.980 回答