2016-03-10 156 views
2

我用這樣的函數轉換int(從傳統的API)向enumgeneric int - >使用模板的枚舉轉換可能嗎?

TestEnum to_test_enum(int value) { 
    TestEnum converted(static_cast<TestEnum>(value)); 
# pragma GCC diagnostic push 
# pragma GCC diagnostic error "-Wswitch" 
    switch (converted) { 
     case TestEnum::A: 
     case TestEnum::B: 
      return converted; 
    } 
# pragma GCC diagnostic pop 

    throw std::runtime_error("wrong value"); 
} 

to_test_enum將引發一個無效值已經傳給to_enum異常,否則返回根據TestEnum值。 pragma可確保在缺少合法值的情況下我將收到編譯器錯誤。

線,如這些現在將轉換爲整數,並做了有效性檢查在運行時:

enum class TestEnum { 
    A = 1, 
    B = 2, 
}; 

auto v1 = to_test_enum(2); 
auto v2 = to_test_enum(3); // will throw 

問題:我不知道是否有可能以某種模板魔法變成一個函數模板:

template<class E> 
E to_enum(int value) { 
    E converted(static_cast<E>(value)); 
    switch (converted) { 
     EACH ELEMENT e IN E: case e: <--- here goes some unrolling magic 
      return converted; 
    } 

    throw std::runtime_error("wrong value"); 
} 

該函數將被用於這樣的:

auto v1 = to_enum<TestEnum>(2); 
auto v2 = to_enum<TestEnum>(3); // will throw 
+0

不,(除非你做了一些欺騙性的東西來聲明枚舉與一些內省)。 – Jarod42

+0

如果添加First和Last或其他佔位符元素來表示可能的範圍,那麼這可能是可能的,但是這會強制枚舉值覆蓋順序範圍的值而沒有任何漏洞,不確定是否要這樣做。 –

+0

我發現了一些有用的預處理器,它可以從同一個文本文件中創建幾個相關的C++東西(例如,創建一個映射枚舉 - > enumNameString,定義enumType_first和enumType_last,並可能定義一個內聯轉換函數)。 –

回答

0

我不確定我是否理解你想要做的事。見下面的想法。您將必須定義自己的map_enum<your_enum>()以將整數映射到枚舉。

#include <map> 
#include <iostream> 

template< typename E > const std::map< int, E >& map_enum() 
{ 
    return 0; 
} 

template < typename E > E to_enum(int ai) 
{ 
    auto m = map_enum<E>(); 
    auto const i = m.find(ai); 
    return i == m.end() ? throw -1 : i->second; 
} 

// { old api 
#define RED 0 
#define GREEN 1 
#define BLUE 2 

int old_api_fun() 
{ 
    return 2; 
} 
// } old api 

// { your code 
enum color_e 
{ 
    red = RED, 
    green = GREEN, 
    blue = BLUE 
}; 

template<> const std::map< int, color_e >& map_enum() 
{ 
    static std::map< int, color_e > m ={ { RED, red }, { GREEN, green }, { BLUE, blue } }; 
    return m; 
} 
// } your code 

int main() 
{ 
    try 
    { 
    auto r = to_enum<color_e>(old_api_fun()); 
    std::cout << "success"; 
    } 
    catch (int) 
    { 
    std::cout << "failed"; 
    } 
    return 0; 
}