[英]How can I eliminate the boilerplate of this enum to string mapping code?
我有以下代碼,它不僅定義了作用域枚舉,而且還具有與之對應的映射,因此我可以將其枚舉器的字符串化版本直接與 iostream 運算符重載一起使用。
enum class ArbitraryNumbers
{
One,
Two,
Three,
Four,
Five
};
namespace
{
using bm_type = boost::bimap<ArbitraryNumbers, std::string>;
bm_type const g_arbitraryNumbersMap = boost::assign::list_of<bm_type::relation>
(ArbitraryNumbers::One, "One")
(ArbitraryNumbers::Two, "Two")
(ArbitraryNumbers::Three, "Three")
(ArbitraryNumbers::Four, "Four")
(ArbitraryNumbers::Five, "Five")
;
}
std::ostream& operator<< (std::ostream& os, ArbitraryNumbers number)
{
auto it = g_arbitraryNumbersMap.left.find(status);
if (it != g_arbitraryNumbersMap.left.end())
{
os << it->second;
}
else
{
os.setstate(std::ios_base::failbit);
}
return os;
}
std::istream& operator>> (std::istream& is, ArbitraryNumbers& number)
{
std::string number_string;
is >> number_string;
auto it = g_arbitraryNumbersMap.right.find(number_string);
if (it != g_arbitraryNumbersMap.right.end())
{
status = it->second;
}
else
{
is.setstate(std::ios_base::failbit);
}
return is;
}
我想以某種可重復使用的方式包裝它。 我認為最好的解決方案將涉及一些宏,最好是這樣的:
BEGIN_SCOPED_ENUM(ArbitraryNumbers)
ENUMERATOR(One)
ENUMERATOR(Two)
ENUMERATOR(Three)
ENUMERATOR(Four)
ENUMERATOR(Five)
END_SCOPED_ENUM()
這非常類似於 MFC,這對我來說主要是立即關閉。 但至少這對眼睛來說要容易得多。 另一點是它消除了樣板文件並且不容易出錯,因為映射不需要與枚舉本身的添加或刪除保持同步。
有沒有辦法用 Boost.Preprocessor、模板技巧或其他一些有用的機制來完成這個任務?
我確實在網上找到了一些想法,但其中大部分是我想避免的手工宏。 我覺得如果我必須采用宏方法,Boost.Preprocessor 將能夠為我做到這一點,但它使用起來非常復雜,我不確定如何使用它來解決這個問題。 此外,我發現的大多數解決方案都已經過時了,我想看看答案是否與 C++03 和 C++14 之間在 STL 和核心語言中引入的功能有所不同。
我只想寫一個數組:
std::string array[] = {"one", "two", "three"};
我想這個問題與自動生成罪表相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.