根据struct member function的值生成状态

时间:2016-11-11 13:37:40

标签: c++ struct states

我目前正在尝试提出一个基于结构生成基于整数的状态的漂亮解决方案。

struct status{
public:
    status();
    /**
     * @brief busy
     * true =  Currently handling a message in manual mode
     * false = Not handling 
     */
    bool busy;
    /**
     * @brief speed
     * Variable containing the current speed 
     * Speed possibilities [FAST;MEDIUM;SLOW]
     */
    int speed;
    /**
     * @brief powered
     * A boolean determining whether it is powered or not.
     * true = ON
     * false = OFF
     */
    bool powered;
    /**
     * @brief direction
     * A boolean determing the direction 
     * true = FORWARD
     * false = BACKWARDS
     */
    bool direction;

};

该函数需要获取struct的实例,并根据成员变量生成唯一的状态。

什么是一个漂亮的解决方案,不涉及手动检查,或设置所有可能性,从而产生状态?

2 个答案:

答案 0 :(得分:3)

您可以使用bitset std::bitset或无符号数字类型)来表示您的独特状态。

您将需要:

  • wget https://curl.haxx.se/download/curl-7.51.0.tar.gz tar xvf curl-7.51.0.tar.gz cd curl-7.51.0 ./configure --with-ssl make sudo make install 的1位。
  • busy的1位。
  • powered的1位。
  • direction的2位。

总的来说,您需要5位来表示所有可能的组合。

示例:

speed

wandbox example

答案 1 :(得分:0)

不如std::bitset,但您可以使用位字段将整个结构存储在单个字节中:

struct status {
public:
    status(Busy busy, Speed speed, Powered powered, Direction direction)
        : busy{busy}, speed{speed}, powered{powered}, direction{direction}, pad{0} {};

    Busy busy : 1;
    Speed speed : 2;
    Powered powered : 1;
    Direction direction : 1;
    unsigned char pad : 3; // pad to 8 bits
};

完整计划:

#include <bitset>
#include <iostream>

#define ENUM_MACRO3(name, v1, v2, v3)\
    enum class name : unsigned char { v1, v2, v3};\
    std::ostream& operator<<(std::ostream& os, name var) {\
        switch (var){\
            case name::v1: return os << #v1;\
            case name::v2: return os << #v2;\
            case name::v3: return os << #v3;\
        }\
        return os;\
    }

#define ENUM_MACRO2(name, v1, v2)\
    enum class name : unsigned char { v1, v2};\
    std::ostream& operator<<(std::ostream& os, name var) {\
        switch (var){\
            case name::v1: return os << #v1;\
            case name::v2: return os << #v2;\
        }\
        return os;\
    }

ENUM_MACRO3(Speed, fast, medium, slow)
ENUM_MACRO2(Busy, handling, not_handling)
ENUM_MACRO2(Powered, on, off)
ENUM_MACRO2(Direction, forwards, backwards)

struct status {
public:
    status(Busy busy, Speed speed, Powered powered, Direction direction)
        : busy{busy}, speed{speed}, powered{powered}, direction{direction}, pad{0} {};

    Busy busy : 1;
    Speed speed : 2;
    Powered powered : 1;
    Direction direction : 1;
    unsigned char pad : 3; // pad to 8 bits
};

int main()
{
    status s{Busy::not_handling,Speed::slow,Powered::off,Direction::backwards};

    std::cout << "Data has size of " << sizeof(status) << '\n';
    std::cout << "busy :" << s.busy << '\n';
    std::cout << "speed :" << s.speed << '\n';
    std::cout << "powered :" << s.powered << '\n';
    std::cout << "direction :" << s.direction << '\n';

    unsigned char val = reinterpret_cast<unsigned char&>(s);
    unsigned int num{val};
    std::cout << num << '\n';
    std::bitset<8> bs{num};
    std::cout << bs << '\n';
    return 0;
}

产地:

Data has size of 1
busy :not_handling
speed :slow
powered :off
direction :backwards
29
00011101

要记住一些要点:

  • Bit fields不可移植。另一种实施可能:
    • 使用多个字节。
    • 反转位。
    • 引入填充以不同方式对齐位。
  • 上面的程序打破了strict aliasing rule
    • 因此,最好通过直接以安全的方式设置位来生成std::bitset的哈希值。
  • 位字段较慢。