2016-04-15 44 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”