2015-09-25 29 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