我正在阅读有关使用变体实现状态机的信息。我尝试创建一个采用变量参数来初始化状态的构造。但是,当定义了构造函数时,我会得到一个警告,它被认为是函数声明。
此外,当我尝试为状态定义setter时,尝试调用此方法会生成编译器错误
这是代码
#include "pch.h"
#include <iostream>
#include <variant>
#include <cassert>
struct DoorState
{
struct DoorOpened {};
struct DoorClosed {};
struct DoorLocked {};
using State = std::variant<DoorOpened, DoorClosed, DoorLocked>;
DoorState()
{
}
DoorState(State & state)
{
m_state = state;
}
void open()
{
m_state = std::visit(OpenEvent{}, m_state);
}
void close()
{
m_state = std::visit(CloseEvent{}, m_state);
}
void lock()
{
m_state = std::visit(LockEvent{}, m_state);
}
void unlock()
{
m_state = std::visit(UnlockEvent{}, m_state);
}
struct OpenEvent
{
State operator()(const DoorOpened&) { return DoorOpened(); }
State operator()(const DoorClosed&) { return DoorOpened(); }
// cannot open locked doors
State operator()(const DoorLocked&) { return DoorLocked(); }
};
struct CloseEvent
{
State operator()(const DoorOpened&) { return DoorClosed(); }
State operator()(const DoorClosed&) { return DoorClosed(); }
State operator()(const DoorLocked&) { return DoorLocked(); }
};
struct LockEvent
{
// cannot lock opened doors
State operator()(const DoorOpened&)
{
std::cout << "DoorOpened" << std::endl;
return DoorOpened();
}
State operator()(const DoorClosed&) { return DoorLocked(); }
State operator()(const DoorLocked&) { return DoorLocked(); }
};
struct UnlockEvent
{
// cannot unlock opened doors
State operator()(const DoorOpened&) { return DoorOpened(); }
State operator()(const DoorClosed&) { return DoorClosed(); }
// unlock
State operator()(const DoorLocked&) { return DoorClosed(); }
};
void set(State state)
{
}
State m_state;
};
int main()
{
//DoorState s(DoorState::DoorOpened);
DoorState s;
s.set(DoorState::DoorOpened);
s.lock();
return 0;
}
答案 0 :(得分:2)
在
s.set(DoorState::DoorOpened);
您要传递类型,应该传递类型的实例,尝试
s.set(DoorState::DoorOpened{});
此更改后,我能够在MSVC 2019(16.1.3)中进行编译
编辑:这是一个处理Scheff和Jarod24注释的编辑,如果取消注释构造函数并编写
,则可能是最令人头疼的解析情况。DoorState s(DoorState::DoorOpened());
这可以使用统一的初始化语法解决,请参见例如 https://arne-mertz.de/2015/07/new-c-features-uniform-initialization-and-initializer_list/
DoorState s{DoorState::DoorOpened{}};
这本来可以解决最棘手的解析问题,但会带来一个新问题:DoorState::DoorOpened{}
将是暂时的,并且永远不会绑定到ctor的输入参数上:
DoorState(State& state)
然后我们需要将其更改为
DoorState(const State& state)
再次感谢Jarod和Scheff指出了这个问题。