c++ - 在 C++ 中使用重新解释转换来扩展嵌套宏

标签 c++ c++11 macros

我偶然发现了下面的代码,并且真的发现理解嵌套宏和其中的类型转换很复杂。

另外,当我尝试编译代码时,我遇到了一个错误

需要解释以下代码。

为什么 BEGIN_STATE_MAP 和 END_STATE_MAP 设置为 Motor.h 中的标签,这对我来说真的很新

提前致谢

电机.h

// the Motor state machine class
class Motor : public StateMachine
{
public:
    Motor() : StateMachine(ST_MAX_STATES) {}

    // external events taken by this state machine
    void Halt();
    void SetSpeed(MotorData*);
private:
    // state machine state functions
    void ST_Idle();
    void ST_Stop();
    void ST_Start(MotorData*);
    void ST_ChangeSpeed(MotorData*);

    // state map to define state function order
    BEGIN_STATE_MAP
        STATE_MAP_ENTRY(ST_Idle)
        STATE_MAP_ENTRY(ST_Stop)
        STATE_MAP_ENTRY(ST_Start)
        STATE_MAP_ENTRY(ST_ChangeSpeed)
    END_STATE_MAP

    // state enumeration order must match the order of state
    // method entries in the state map
    enum E_States {
        ST_IDLE = 0,
        ST_STOP,
        ST_START,
        ST_CHANGE_SPEED,
        ST_MAX_STATES
    };
};
#endif //MOTOR_H

什么是 BEGIN_STATE_MAP 和 END_STATE_MAP,我发现这个定义真的很新, BEGIN_STATE_MAP 和 END_STATE_MAP 是在下面的头文件中定义的宏。

状态机.h

#ifndef STATE_MACHINE_H
#define STATE_MACHINE_H
#include <stdio.h>
#include "EventData.h"

struct StateStruct;

// base class for state machines
class StateMachine
{
public:
    StateMachine(int maxStates);
    virtual ~StateMachine() {}
protected:
    enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN };
    unsigned char currentState;
    void ExternalEvent(unsigned char, EventData* = NULL);
    void InternalEvent(unsigned char, EventData* = NULL);
    virtual const StateStruct* GetStateMap() = 0;
private:
    const int _maxStates;
    bool _eventGenerated;
    EventData* _pEventData;
    void StateEngine(void);
};

typedef void (StateMachine::*StateFunc)(EventData *);
struct StateStruct
{
    StateFunc pStateFunc;
};

#define BEGIN_STATE_MAP \
public:\
const StateStruct* GetStateMap() {\
    static const StateStruct StateMap[] = {

#define STATE_MAP_ENTRY(entry)\
    { reinterpret_cast<StateFunc>(entry) },

#define END_STATE_MAP \
    { reinterpret_cast<StateFunc>(NULL) }\
    }; \
    return &StateMap[0]; }

#define BEGIN_TRANSITION_MAP \
    static const unsigned char TRANSITIONS[] = {\

#define TRANSITION_MAP_ENTRY(entry)\
    entry,

#define END_TRANSITION_MAP(data) \
    0 };\
    ExternalEvent(TRANSITIONS[currentState], data);

#endif

事件数据.h

#ifndef EVENT_DATA_H
#define EVENT_DATA_H

class EventData
{
public:
   virtual ~EventData() {};
};
#endif //EVENT_DATA_H

当我尝试编译上面的代码时,下面是遇到的错误

错误

-------------- Build: Debug in StateMachine (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -Wall -fexceptions -g -pedantic -Wzero-as-null-pointer-constant -std=c++0x -Wextra -Wall  -c C:\Users\xprk569\StateMachine\main.cpp -o obj\Debug\main.o
In file included from C:\Users\xprk569\StateMachine\main.cpp:2:0:
C:\Users\xprk569\StateMachine\Motor.h: In member function 'virtual const StateStruct* Motor::GetStateMap()':
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
     { reinterpret_cast<StateFunc>(entry) },
                                        ^
C:\Users\xprk569\StateMachine\Motor.h:29:9: note: in expansion of macro 'STATE_MAP_ENTRY'
         STATE_MAP_ENTRY(ST_Idle)
         ^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
     { reinterpret_cast<StateFunc>(entry) },
                                        ^
C:\Users\xprk569\StateMachine\Motor.h:30:9: note: in expansion of macro 'STATE_MAP_ENTRY'
         STATE_MAP_ENTRY(ST_Stop)
         ^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
     { reinterpret_cast<StateFunc>(entry) },
                                        ^
C:\Users\xprk569\StateMachine\Motor.h:31:9: note: in expansion of macro 'STATE_MAP_ENTRY'
         STATE_MAP_ENTRY(ST_Start)
         ^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
     { reinterpret_cast<StateFunc>(entry) },
                                        ^
C:\Users\xprk569\StateMachine\Motor.h:32:9: note: in expansion of macro 'STATE_MAP_ENTRY'
         STATE_MAP_ENTRY(ST_ChangeSpeed)
         ^
C:\Users\xprk569\StateMachine\StateMachine.h:43:39: error: invalid cast from type 'int' to type 'StateFunc {aka void (StateMachine::*)(EventData*)}'
     { reinterpret_cast<StateFunc>(NULL) }\
                                       ^
C:\Users\xprk569\StateMachine\Motor.h:33:5: note: in expansion of macro 'END_STATE_MAP'
     END_STATE_MAP
     ^
Process terminated with status 1 (0 minute(s), 0 second(s))
5 error(s), 0 warning(s) (0 minute(s), 0 second(s))

能否解释一下为什么 Motor.h 中的宏是这样写的, 为什么在 StateMachine.h 中这样声明 为什么会抛出错误?

提前致谢

最佳答案

看起来这段代码依赖于一些非标准的编译器扩展/错误。

要让它编译(不知道它是否真的有效)你需要用完全限定的成员函数指针替换函数名:

例如

BEGIN_STATE_MAP
    STATE_MAP_ENTRY(&Motor::ST_Idle)
    STATE_MAP_ENTRY(&Motor::ST_Stop)
    STATE_MAP_ENTRY(&Motor::ST_Start)
    STATE_MAP_ENTRY(&Motor::ST_ChangeSpeed)
END_STATE_MAP

在那之后,你需要想办法克服不合格的转换:

/tmp/gcc-explorer-compiler116314-75-1uiyu0/example.cpp: In member function 'virtual const StateStruct* Motor::GetStateMap()':
44 : error: invalid cast from type 'long int' to type 'StateFunc {aka void (StateMachine::*)(EventData*)}'
{ reinterpret_cast<StateFunc>(NULL) }\
^
83 : note: in expansion of macro 'END_STATE_MAP'

这种转换是完全非法的。如果我是你,我会把代码扔进垃圾桶并重写 - 或者使用经过验证的状态机框架,如 boost 元状态机或 boost 状态图。

关于c++ - 在 C++ 中使用重新解释转换来扩展嵌套宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36620755/

相关文章:

C++:指向数据成员或特征的指针?

macros - 在 Sublime Text 3 中自动选择粘贴的文本

clojure - 如何在 Clojure 中映射宏?

c++ - 如何在 C++ 中为多个类类型指定相同的模板化成员函数?

c++ - 在单个节点中有 2 个项目的链接节点

c++ - 为什么这些 shared_ptr 不指向同一个容器?

templates - C++模板静态整数常量: out of class definition

c++ - 在单例中使用已删除的复制构造函数

c++ - 通过读取文件检测 C++ 中的空行

android - 如何在 Qt 中使用 Google-Cloud-Messaging API