Boost.MSM中transition_table和state_flod的容量问题
Solution
示例代码里的struct transition_table : mpl::vector
改为继承boost::fusion::vector
在C++11的标准下就能解放vector容量上限
根据Boost中的解释
Question: Why do I get a very long compile error when I define more than 20 rows in the transition table?
Answer: MSM uses Boost.MPL under the hood and this is the default maximum size. Please define the following 3 macros before including any MSM headers:
#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS #define BOOST_MPL_LIMIT_VECTOR_SIZE 30 // or whatever you need #define BOOST_MPL_LIMIT_MAP_SIZE 30 // or whatever you need
Question: Why do I get this error: ”error C2977: ‘boost::mpl::vector’ : too many template arguments”?
Answer: The first possibility is that you defined a transition table as, say, vector17 and have 18 entries. The second is that you have 17 entries and have a composite state. Under the hood, MSM adds a row for every event in the composite transition table. The third one is that you used a mpl::vector without the number of entries but are close to the MPL default of 50 and have a composite, thus pushing you above 50. Then you need mpl/vector60/70….hpp and a mpl/map60/70….hpp
Question: Why do I get a very long compile error when I define more than 10 states in a state machine?
Answer: MSM uses Boost.Fusion under the hood and this is the default maximum size. Please define the following macro before including any MSM headers:
#define FUSION_MAX_VECTOR_SIZE 20 // or whatever you need
在不预定义宏的情况下无法修改。而且哪怕定义了,也是支撑不起大规模的状态机的(需要自己实现mpl/map60等等)
或许可以用fusion.C++11
快速实现?
仍然需要使用上述宏定义,修改超出预定义的上限(50)后, 会访问例如"boost/mpl/vector/vector90.hpp"
目录,不修改Boost工程的情况下无法实现,不利于团队代码协作
Analysis
近来项目里大量的用到了状态机,Boost里面有两个状态机库,一个是StateChart
,一个是Meta State Machine
。StateChart
没怎么了解过,主要用的是MSM。实践下来还是比较好用的,能够比较直观的组织代码和提高稳定性。
到后面写得状态机越来越复杂时,发现示例代码里面transition_table
所继承的mpl::vector
容量非常有限。Boost.MPL是个很早版本的元编程库(C++03年代),这个mpl里的vector能够承载的数量是靠手写模板一个个实现的。
查阅了下,MSM的文档里面提到了用了Fusion
(另一个Boost模板库,同样的库还有Boost.Hana)来保存表
State objects are built automatically with the state machine. They will exist until state machine destruction. MSM is using Boost.Fusion behind the hood. This unfortunately means that if you define more than 10 states, you will need to extend the default
而Fusion::vector
中提到
For C11 compilers, the variadic function interface has no upper bound.
For C03 compilers, the The variadic form accepts 0 to FUSION_MAX_VECTOR_SIZE elements, where FUSION_MAX_VECTOR_SIZE is a user definable predefined maximum that defaults to 10. Example:
C++11中扩展了可变参数模板,可以解放以前手动定义n个模板参数的重复劳动。
唯一疑惑的是MSM使用了Fusion,示例代码里面却用了旧的mpl库,使用Fusion能够无缝替换
Updated 2022-01-06
从Boost文档里可以看到MSM.v2
推出的时候是Boost 1.44
,August 13th, 2010 17:00 GMT,那时候C++11
还没正式推出,使用了大量的MPL代码,这部分无法修改。
而MPL呢,则更老了, Boost 1.32
,时间是November 19th, 2004 12:00 GMT,是c++03
的版本
这两个库都是在C++11
正式推出之前就已经发布了,采用了大量c++03
模板元编程代码,有一定的局限性(正上文已经提到过)