2016-04-15 80 views
1

我需要一個將類型轉換爲類型To(To和From是枚舉)的函數,但是枚舉E1只能轉換爲E2,如果用戶試圖獲取錯誤例如將E1轉換爲E3。C++轉換特定的枚舉對

template<typename From, typename To> 
static To map(From f){ 
    return static_cast<To>(f); 
} 

我該怎麼做? 謝謝!

+2

Go with template specialization –

+3

你能舉個例子嗎? –

回答

2

一個可能的解決方案:static_assert

template<typename From, typename To> 
static To map(From f) { 
    static_assert(!(std::is_same<From, E1>::value && std::is_same<To, E3>::value), 
        "cannot cast from E1 to E3"); 

    return static_cast<To>(f); 
} 

auto main() -> int { 
    E1 a; 
    const auto b = map<E1, E2>(a); // compiles 
    const auto c = map<E1, E3>(a); // won't compile 

    return 0; 
} 
+0

這很有趣您的解決方案,但是static_assert在編譯時評估,From和To在運行時 –

+0

' - >'是怎麼回事?現在是C++的一部分嗎?哦,我明白了,main是一個lambda函數?涼! – smac89

+0

Ionut是的,正確的。你的代碼如何調用函數? @ Smac89是的,你可以像現在這樣聲明main(...) – CppChris

1

使用模板專業化,您可以指定如何爲不同類型工作。看看下面的例子。

template<typename To, typename From> 
To map(From f){ 
    return static_cast<To>(f); 
} 

template<> 
E2 map(E1 f){ 
    return static_cast<E2>(f); 
} 

map()函數調用時E1類型,那麼專業的模板函數執行,而不是正常的模板功能。但除了類型E1正常的模板函數被調用。

這將強制用戶僅將E1轉換爲E2。如果你想拋出異常或assert修改定義爲你的願望。

0

你需要使用模板特殊化。另外,您需要將To模板參數移動爲第一個模板參數,因爲它將是返回類型,編譯器將無法推斷它。

首先,創建主模板的功能,但不提供它的實現:

template<typename To, typename From> 
To map(From from); 

現在,這是有意義的映射做到專業化:

template<> 
E2 map(E1 from) 
{ 
    return static_cast<E2>(from); 
} 

正如你」已經提供了映射的專業化,如果你試圖調用那些沒有的映射,那麼你會得到一個錯誤。例如,在VS2012如果你這樣做:

E3 value = map<E3>(e1_value); 

,因爲是在映射沒有實現你會得到一個「unresovled外部符號」錯誤。

0

以下是使用Concepts的解決方案。根據我的知識,僅在gcc6中實現了概念,這仍然是實驗性的。

#include <type_traits> 

enum E1{}; 
enum E2{}; 
enum E3{}; 

template <class T, class U> concept bool Same = std::is_same<T,U>::value; 

template<typename From, typename To> 
static To map(From f) 
requires !(Same<From, E1> && Same<To, E3>) 
{ 
    return static_cast<To>(f); 
} 

int main() 
{ 
    E1 e1; 
    E2 e2; 
    E3 e3; 

    map<E1, E2>(e1); // Ok 
    map<E1, E3>(e1); // Compile Error ! 
} 

將顯示錯誤如下:

prog.cc: In function 'int main()': 
prog.cc:23:19: error: cannot call function 'To map(From) requires predicate(!((Same<From, E1>) && (Same<To, E3>))) [with From = E1; To = E3]' 
    map<E1, E3>(e1); 
       ^
prog.cc:10:11: note: constraints not satisfied 
static To map(From f) 
      ^~~ 

http://melpon.org/wandbox/permlink/mEG3Rl5jaMXj0GVg

編譯實驗版本的gcc 6.0:

$克++ prog.cc -Wall -Wextra -I/USR /local/boost-1.60.0/include -std = gnu ++ 1z「-fconcepts」