[英]How to restrict conversion from int to enum class?
如果我有一個像這樣的enum class
:
enum class Weekday {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
我有一個從int
到Weekday
的轉換:
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
進行抽象。 如果給定值在范圍內( First
, Last
],則分配該值。如果不是,則拋出異常。根據無效輸入的頻率,異常可能不是正確的做法,如果錯誤輸入很常見,則幾乎沒有異常,但在這里它有助於使示例保持簡單。
現在調用是一個簡單的問題
enum class Weekday
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
Last, // added
First = Monday // added
};
然后
Weekday day = do_conversion<Weekday>(value);
轉換產生的所有噪音都不會影響轉換所需的任何內容,因此任何正在讀取或編寫該代碼的人都可以繼續他們的工作。
但是如果你在沒有First
和Last
的enum
上使用它呢? 編譯器消息可能會變得奇怪,因此最好幫助用戶一點。 以下已從如何檢測class中是否存在特定成員變量? 使其更易於使用。 絕對花時間閱讀答案以了解發生了什么。 我還沒有想出一個體面的方法來結合HasFirst
和HasLast
。 請發表評論,讓我知道你是否有。
#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.