簡體   English   中英

如何限制從 int 到枚舉 class 的轉換?

[英]How to restrict conversion from int to enum class?

如果我有一個像這樣的enum class

enum class Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

我有一個從intWeekday的轉換:

Weekday day = static_cast<int>(value);

要檢查為轉換提供的值是否有效,我應該有代碼:

if (value != 0 && value != 1 && value !=2 && value !=3 && value != 4 && value != 5 && value != 6) { 
  do_conversion(value); 
}

太丑了有什么好的方法可以做到這一點嗎?

枚舉 class 的默認基礎類型是 integer。 因此,要檢查 integer 是否在可接受的枚舉值范圍內,您可以使用static_cast<int>將其與可接受的枚舉值的范圍進行比較:

if (value >= static_cast<int>(Weekday::Monday) && value <= static_cast<int>(Weekday::Sunday))
{
    do_conversion(value);
}

從表面上看,這可能過於復雜,但它可以很好地概括,並且模板 voodoo 可以隱藏在遠離視線的 header 中。

#include <stdexcept>
template <class TYPE>
TYPE do_conversion(int value)
{
    if (value >= static_cast<int>(TYPE::First) &&
        value < static_cast<int>(TYPE::Last))
    {
        return static_cast<TYPE>(value);
    }
    throw std::out_of_range("Inv value");
}

所有轉換都移至 function 以降低噪聲。 有效范圍通過額外的枚舉值First and Last進行抽象。 如果給定值在范圍內( FirstLast ],則分配該值。如果不是,則拋出異常。根據無效輸入的頻率,異常可能不是正確的做法,如果錯誤輸入很常見,則幾乎沒有異常,但在這里它有助於使示例保持簡單。

現在調用是一個簡單的問題

enum class Weekday
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
    Last,           // added
    First = Monday  // added
};

然后

Weekday day = do_conversion<Weekday>(value);

轉換產生的所有噪音都不會影響轉換所需的任何內容,因此任何正在讀取或編寫該代碼的人都可以繼續他們的工作。

但是如果你在沒有FirstLastenum上使用它呢? 編譯器消息可能會變得奇怪,因此最好幫助用戶一點。 以下已從如何檢測class中是否存在特定成員變量? 使其更易於使用。 絕對花時間閱讀答案以了解發生了什么。 我還沒有想出一個體面的方法來結合HasFirstHasLast 請發表評論,讓我知道你是否有。

#include <stdexcept>
#include <type_traits>
template <typename T, typename = int>
struct HasFirst : std::false_type { };

template <typename T>
struct HasFirst <T, decltype((void) T::First, 0)> : std::true_type { };

template <typename T, typename = int>
struct HasLast : std::false_type { };

template <typename T>
struct HasLast <T, decltype((void) T::Last, 0)> : std::true_type { };

template <class TYPE>
TYPE do_conversion(int value)
{
    static_assert(HasFirst<TYPE>::value, "enum missing First");
    static_assert(HasLast<TYPE>::value, "enum missing Last");
    if (value >= static_cast<int>(TYPE::First) &&
        value < static_cast<int>(TYPE::Last))
    {
        return static_cast<TYPE>(value);
    }
    throw std::out_of_range("Inv value");
}

現在,如果enum缺少最重要的元值,編譯器可以通過簡單的錯誤消息告訴它們。

測試用例

暫無
暫無

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

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