2015-09-25 45 views
3

我有下面的代码,不仅定义了范围枚举,但也有一个相应的映射,所以我可以直接使用它的枚举器的字符串版本与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和核心语言中引入的功能不同。

+0

做任意号码必须遵循另一个?或者他们可以有不同的时间间隔? –

+0

这可能适用于X宏。 –

+0

看看这个:https://en.wikipedia.org/wiki/X_Macro – peje

回答

-2

我只是写一个数组:

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

我想这个问题是一样的,与自动生成罪桌。

+0

你能解释这与生成_sin-tables_ [原文如何?]有关吗? – sehe

+0

@sehe:是的,通常C++不支持自动生成大型表,您需要为此做一个for-loop,但如果您想要一个像sin-table这样的静态表,那不是一种替代方案。基本上你需要代码生成来获得这样的表。 – tp1

+0

这似乎与我无关。毕竟,没有函数(比如罪)来调用enum成员的名字作为字符串。所以你不能“首先需要为此做一个for-loop”。 – sehe