简体   繁体   English

如何消除此枚举到字符串映射代码的样板?

[英]How can I eliminate the boilerplate of this enum to string mapping code?

I have the following code that not only defines a scoped enumeration, but also has a corresponding mapping with it so I can use the stringized version of its enumerators directly with iostream operator overloads.我有以下代码,它不仅定义了作用域枚举,而且还具有与之对应的映射,因此我可以将其枚举器的字符串化版本直接与 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;
}

I'd like to wrap this in some sort of reusable fashion.我想以某种可重复使用的方式包装它。 I think the best solution will involve some macros, ideally something like this:我认为最好的解决方案将涉及一些宏,最好是这样的:

BEGIN_SCOPED_ENUM(ArbitraryNumbers)
    ENUMERATOR(One)
    ENUMERATOR(Two)
    ENUMERATOR(Three)
    ENUMERATOR(Four)
    ENUMERATOR(Five)
END_SCOPED_ENUM()

This is very MFC-like, which is mostly an immediate turn-off for me.这非常类似于 MFC,这对我来说主要是立即关闭。 But at least this is MUCH easier on the eyes.但至少这对眼睛来说要容易得多。 Another point is that it eliminates boilerplate and is less error prone since the mapping doesn't need to be kept in sync with additions or removals to and from the enumeration itself.另一点是它消除了样板文件并且不容易出错,因为映射不需要与枚举本身的添加或删除保持同步。

Is there a way I can accomplish this with Boost.Preprocessor, template trickery, or some other useful mechanic?有没有办法用 Boost.Preprocessor、模板技巧或其他一些有用的机制来完成这个任务?

I did find some ideas online but most of it was hand-spun macros, which I want to avoid.我确实在网上找到了一些想法,但其中大部分是我想避免的手工宏。 I feel like if I have to go the macro approach that Boost.Preprocessor will be able to do this for me, but it's very complex to use and I'm not sure how to use it to solve this problem.我觉得如果我必须采用宏方法,Boost.Preprocessor 将能够为我做到这一点,但它使用起来非常复杂,我不确定如何使用它来解决这个问题。 Also most of the solutions I found were really dated, and I want to see if answers would be different with features introduced in STL and core language since between C++03 and C++14.此外,我发现的大多数解决方案都已经过时了,我想看看答案是否与 C++03 和 C++14 之间在 STL 和核心语言中引入的功能有所不同。

i'd just write an array:我只想写一个数组:

std::string array[] = {"one", "two", "three"};

I guess the issue is the same as with generating sin-tables automatically.我想这个问题与自动生成罪表相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM