繁体   English   中英

C ++投射特定的枚举对

[英]C++ cast specific pairs of enums

我需要一个将类型From转换为类型To(To和From是枚举)的函数,但枚举E1只能转换为E2,如果用户试图将E1转换为E3,我需要得到一个错误。

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);
}

当使用类型E1调用map()函数时,将执行专用模板函数而不是普通模板函数。 但是调用除了E1类型的普通模板函数之外。

这将强制用户仅将E1E2 如果你想抛出异常或assert修改定义你的愿望。

您需要使用模板专业化。 此外,您将要将To模板参数移动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);

您将获得“未解决的外部符号”错误,因为映射没有实现。

以下是使用Concepts的解决方案。 据我所知,概念仅在gcc6中实现,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的实验版编译:

$ g ++ prog.cc -Wall -Wextra -I / usr / local / boost-1.60.0 / include -std = gnu ++ 1z“-fconcepts”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM