我需要一個將類型轉換爲類型To(To和From是枚舉)的函數,但是枚舉E1只能轉換爲E2,如果用戶試圖獲取錯誤例如將E1轉換爲E3。C++轉換特定的枚舉對
template<typename From, typename To>
static To map(From f){
return static_cast<To>(f);
}
我該怎麼做? 謝謝!
我需要一個將類型轉換爲類型To(To和From是枚舉)的函數,但是枚舉E1只能轉換爲E2,如果用戶試圖獲取錯誤例如將E1轉換爲E3。C++轉換特定的枚舉對
template<typename From, typename To>
static To map(From f){
return static_cast<To>(f);
}
我該怎麼做? 謝謝!
一個可能的解決方案: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;
}
使用模板專業化,您可以指定如何爲不同類型工作。看看下面的例子。
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
修改定義爲你的願望。
你需要使用模板特殊化。另外,您需要將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外部符號」錯誤。
以下是使用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」
Go with template specialization –
你能舉個例子嗎? –