C ++ 11类型到枚举映射? [英] C++11 type to enum mapping?

查看:156
本文介绍了C ++ 11类型到枚举映射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举:

enum E
{
    TYPE_FLOAT,
    TYPE_CHAR,
    TYPE_INT
}

而我想创建一个编译时映射以获得类型的适当的E:

And I want to create a compile-time mapping to get the appropriate E for a type like:

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'

这是什么最好的方法?

Whats the best way to do this? And why the error?

推荐答案

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

It depends on how you use these constant expressions.

ODR(一个定义规则)规定

The ODR (one-definition rule) states that


(§3.2/ 2)[...]其名称显示为可能评估的表达式是odr使用,除非它是满足出现在常量表达式(5.19)中的要求的对象,并且立即应用左值到右值转换(4.1)。 [...]

(§3.2/2) [...] A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied. [...]

(然后,许多特殊规则,异常和异常都会出现。)

(And then, lots of special rules, exceptions and exceptions of the exceptions follow.)

odr使用的任何变量都必须有一个定义。你的常量表达式有一个声明,但不是一个定义,所以这很好,除非你使用其中之一。

Any variable that is odr-used, must have exactly one definition. Your constant expressions have a declaration, but not a definition, so this goes well unless you odr-use one of them.

例如: p>

For example, the following goes well:

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

但这不会:

void f(const E &)
{ }

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

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

because f requires a (const) reference, so the lvalue-to-rvalue conversion cannot be applied immediately, hence this constitutes an odr-use. The compiler will complain that it misses a definition.

(注释:由于ShafikYaghmour发现(见注释),如果编译器使用优化,为了重现编译器的抱怨,使用 -O0 标志(或类似的,取决于编译器)。)

(Remark. As ShafikYaghmour found (see the comments), you may not get a complaint if the compiler uses optimization, as the references may be optimized away. To reproduce the compiler complaint, use the -O0 flag (or similar, depending on the compiler).)

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

To solve the problem, the required definition can be provided in the usual way, i.e. outside the struct-definition:

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

但是因为这必须发生在.cpp(而不是头文件)

But since this would have to happen in the .cpp (not the header file), you'll end up having to maintain the declarations and definitions in two different places, which is cumbersome.

您刚才在注释中建议的解决方案,即定义一个constexpr(和inline)function,sounds right:

The solution you've just suggested in your comment, i.e. define a constexpr (and inline) function, sounds right:

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

这篇关于C ++ 11类型到枚举映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆