[英]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.