簡體   English   中英

在編譯時將整數轉換為位掩碼而不使用宏

[英]Converting an integer to a bitmask in compile time not using macro

TLDR:提供一個帶有 constexpr 構造函數的“位掩碼”類,該構造函數在編譯時根據輸入參數(應用位移位)創建位掩碼,可以用來代替類似函數的 MACRO。

我正在嘗試實現一個將事件存儲為位標志的事件管理器。 這將是 RTOS 功能(例如事件標志組)的包裝器

我想以這種方式指定事件

enum Event
{
    FOO,
    BAR,
    BAZ,
};

不是這樣:

// This construct is harder to maintain and easier to make a mistake
enum Event
{
    FOO = 0b0001,
    BAR = 0b0010,
    BAZ = 0b0100,
};

然后將以這種方式使用這些事件:

class EventService
{
    uint32_t current_events;

public:
    void set_event(const EventMask ev)
    {
        current_events |= ev.mask;
    }

    bool check_event(const EventMask ev)
    {
        const bool was_set = current_events & ev.mask != 0;
        current_events &= ~(ev.mask);
        return was_set;
    }

};

EventService s;

void event_producer()
{
    s.set_event(Event::FOO); 
}

void event_handler()
{
    if(s.check_event(Event::FOO))
    {
        // do something;
    }

    if(s.check_event(Event::BAR))
    {
        // do something else;
    }

    if(s.check_event(Event::BAZ))
    {
        // do something else;
    }
}

因此,我使用 constexpr 構造函數實現了一個輔助類EventMask ,它只是進行位移並將其存儲為 const 成員。

struct EventMask
{    
    const uint32_t mask;

    template<typename Enum>
    constexpr EventMask(Enum event_id) : mask(1u << event_id)
    {
        static_assert(std::is_enum<Enum>::value, "Enum required.");
        constexpr_assert(event_id <= MAX_ID);
    }
};

但不幸的是,這些位掩碼對象不是在使用check_eventset_event時在構建時創建的。 是放在一起的整個示例。

set_event(Event::FOO);
check_event(Event::BAZ); //this should fail in the conpile time because I set BAZ to be higher then MAX_ID

我知道我可以在set_eventcheck_event周圍有一個 MACRO 包裝器,但我相信有一種更現代的方式(可能我一開始就不理解 constexpr。)另一方面,我可以有一個帶有模板的模板參數N和 body 1u << N但這會使代碼膨脹,不是嗎?

我一直在考慮consteval但這將不允許發送顯示為有效用例的運行時事件(例如作為配置存儲在某處)

不是一個真正的答案,為什么你的斷言不起作用,但我避免了這個問題:

enum class Bits
{
    FOO,
    BAR,
    BAZ,
};

enum class Event
{
    FOO = 1llu << int(Bits::FOO),
    BAR = 1llu << int(Bits::BAR),
    BAZ = 1llu << int(Bits::BAZ),
};

Event operator |(const Event &lhs, const Event &rhs) {
    return Event(int(lhs) | int(rhs));
}

Event x = Event::FOO | Event::BAR;

很多樣板,但它的工作原理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM