2

我正在尝试使用最终状态机和 std::variant<..>

std::variant 将保存所有可能的状态状态将在 State 类中定义。

我想将 std::monostate 作为第一种状态变体,以将其用作“不更改状态”值。所以定义是:第一种是std::monostate,第二种是fsm的初始状态。

由于 std::variant 被初始化为它的第一个元素,我想在构造函数中使用 emplace<1> 。

template <typename StateVariant>
class fsm
{
public:
    StateVariant state;
    fsm()
    {
        state.emplace<1>();
    };
};

struct Initial{};
struct Running{};

using State = std::variant<std::monostate,Initial,Running>;

fsm<State> myFSM;

但这会产生编译时错误:

..\fsm_emplace.cpp: In constructor 'fsm<StateVariant>::fsm()':
..\fsm_emplace.cpp:15:20: error: expected primary-expression before ')' token
   15 |   state.emplace<1>();};

但是,当我在非模板代码中使用相同的构造时:

State myState;

void setup()
{
    myState.emplace<1>();
}

emplace 功能是否有使用限制?

4

2 回答 2

1

由于状态取决于模板名称,因此您必须添加template

state.template emplace<1>();
于 2020-07-09T15:25:08.237 回答
1

emplace 功能是否有使用限制?

我不知道正式规则的措辞,但你需要在template这里使用关键字。clang 给出了一个更具描述性的错误“在依赖模板名称 'emplace' 之前缺少 'template' 关键字”。更改state.emplace<1>();state.template emplace<1>();将修复构建错误。

尽管对于它的价值,我也会考虑in_place_index_t在成员初始化程序中使用(由 Nicol Bolas 在评论中建议)是一个更优雅的解决方案。

于 2020-07-09T15:25:56.787 回答