繁体   English   中英

C++11 类型到枚举映射?

[英]C++11 type to enum mapping?

我有一个枚举:

enum E
{
    TYPE_FLOAT,
    TYPE_CHAR,
    TYPE_INT
}

我想创建一个编译时映射来为以下类型获取适当的 E:

GetE<float> // returns TYPE_FLOAT
GetE<char> // returns TYPE_CHAR
GetE<int> // returns TYPE_INT

我想到了:

template<class T> struct GetE;

template<> struct GetE<float> { static constexpr E type = TYPE_FLOAT; };
template<> struct GetE<char> { static constexpr E type = TYPE_CHAR; };
template<> struct GetE<int> { static constexpr E type = TYPE_INT; };

但我收到如下错误:

undefined reference to `GetE<int>::type'

什么是最好的方法来做到这一点? 为什么会出错?

这取决于您如何使用这些常量表达式。

ODR(一个定义规则)指出

(§3.2/2) [...] 名称作为潜在求值表达式出现的变量是 odr 使用的,除非它是满足出现在常量表达式 (5.19) 和左值到-立即应用右值转换 (4.1)。 [...]

(然后,许多特殊规则、例外情况和例外情况的例外情况也随之而来。)

任何odr 使用的变量,必须只有一个定义。 你的常量表达式有一个声明,但没有定义,所以这很顺利,除非你 odr-use 其中一个。

例如,以下情况很顺利:

int main() {
  E e = GetE<float>::type;
  return 0;
}

但这不会:

void f(const E &)
{ }

int main() {
  f(GetE<float>::type);
  return 0;
}

因为f需要一个 (const) 引用,所以不能立即应用左值到右值的转换,因此这构成了 odr 使用。 编译器会抱怨它错过了一个定义。

(备注。正如 ShafikYaghmour 发现的(见评论),如果编译器使用优化,您可能不会收到投诉,因为引用可能会被优化掉。要重现编译器投诉,请使用-O0标志(或类似的,取决于编译器))

为了解决这个问题,可以通过通常的方式提供所需的定义,即在struct-definition之外:

constexpr E GetE<float>::type;
constexpr E GetE<char>::type;
constexpr E GetE<int>::type;

但是由于这必须发生在 .cpp(而不是头文件)中,因此您最终必须在两个不同的地方维护声明和定义,这很麻烦。

您刚刚在评论中建议的解决方案,即定义一个 constexpr(和内联)函数,听起来不错:

template <class T> constexpr E GetE();

template <> constexpr E GetE<float>()
{ return TYPE_FLOAT; }

template <> constexpr E GetE<char>()
{ return TYPE_CHAR; }

template <> constexpr E GetE<int>()
{ return TYPE_INT; }

void f(const E &)
{ }

int main() {
  E e = GetE<float>();

  f(GetE<float>());

  return 0;
}

静态成员变量需要在类作用域之外定义

class C {
    const static int x = 5;
};

decltype(C::x) C::x;

也许是因为您忘记在枚举定义后放置分号,这在 LiveWorkSpace 中对我有用:

#include <iostream>

enum E
{
   TYPE_FLOAT,
   TYPE_CHAR,
   TYPE_INT
} ;

template<class T> struct GetE;

template<> struct GetE<float> { static constexpr E type = TYPE_FLOAT; };
template<> struct GetE<char> { static constexpr E type = TYPE_CHAR; };
template<> struct GetE<int> { static constexpr E type = TYPE_INT; };

int main()
{
    std::cout << GetE<int>::type << std::endl ;
}

这是代码的链接http://liveworkspace.org/code/nHqUe $6

暂无
暂无

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

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