[英]scanf() with C++ enums
以下是我們的代碼庫中的典型情況。
enum ConfigOption { CONFIG_1=1, CONFIG_2=2, CONFIG_3=3 }
ConfigOption cfg1, cfg2;
sscanf(s, "%d", &cfg1);
這是一個內部使用的仿真軟件。 沒有分發。 易於維護和正確性非常重要。 可移植性和用戶界面 - 不是真的。
問題是c ++中的enum
不一定是int
。 因此,我們會收到編譯器警告,並且在使用其他編譯器或啟用優化時可能會出現錯誤行為。
一種解決方案就是將&cfg
為int*
。 但是,這不會捕獲編譯器決定在enum
分配int
以外的東西的情況。
所以我提出了以下解決方案:
template<typename T> inline
int& eint(T& enum_var) {
assert(sizeof(T) == sizeof(int));
return (int&)enum_var;
}
現在使用scanf
如下:
sscanf(s, "%d", &eint(cfg1));
我很想聽聽上述問題的意見和其他(更好的)解決方案。 請記住,其中一個目標是保持代碼簡單。 這不是“生產質量”的東西,你添加的越多 - 維護就越困難。
如果你有像vs2010這樣的現代編譯器,你可以指定枚舉元素的大小
enum class ConfigOption: unsigned int {CONFIG_1=1, CONFIG_2=2, CONFIG_3=3};
它在C ++ 0x中的新功能
我的解決方案是將枚舉強制到最小尺寸。這就是微軟在他們的DirectX頭文件中為他們的枚舉所做的事情(我不得不承認這是一個很好的技巧)。
他們通過添加如下虛擬枚舉來強制枚舉的大小等於int:
typedef enum
{
fooo = 1,
baar = 2,
___Force32Bit = ~0UL
} MyEnum;
現在枚舉總是至少是int的大小。
如果你願意,你可以把它放在頂部..這個強迫enum的大小很長:
typedef enum
{
fooo = 1,
baar = 2,
___Force64Bit = ~0ULL
} MyEnum;
我知道,這不是一個超級干凈的解決方案。 我認為這樣的解決方案不存在,並且到目前為止,強制執行最小尺寸對我來說效果很好。 如果你從32位到64位代碼,你可能需要調整代碼,但通常在這些情況下你必須檢查代碼的某些部分,所以沒有大問題。
順便說一句 - 對不起C代碼,我知道這個問題被標記為C ++,但我是C-guys :-)
為什么不把它作為一個實際的int
讀取?
enum ConfigOption { CONFIG_1=1, CONFIG_2=2, CONFIG_3=3 };
ConfigOption cfg1;
int i;
sscanf(s, "%d", &i);
cfg1 = i;
這樣你就可以進行更全面的有效性檢查(例如測試讀取整數是否在你的enum
類型范圍內)。
(當然,如果您一直擔心檢測錯誤,對於這樣的簡單解析,您應該使用strtol
或strtoul
而不是sscanf
。)
您可以嘗試使用boost::lexical_cast
,或者如果您不使用boost
並且不想在這種情況下開始使用它,您可以自己編寫一個簡化版本。 舉個例子來看看這個SO答案 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.