c++ 11类型到枚举的映射
C++11 type to enum mapping?
我有一个enum:
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)[…如果变量名出现在潜在求值表达式中,则不建议使用,除非它是一个对象,满足出现在常量表达式中(5.19)的要求,并且立即应用左值到右值的转换(4.1)。[…]
(然后,许多特殊的规则,例外和例外的例外。)
任何是奇数使用的变量,必须只有一个定义。你的常量表达式有一个声明,但没有定义,所以这很好,除非你经常使用其中一个。
例如:
int main() {
E e = GetE<float>::type;
return 0;
}
但这不是:
void f(const E &)
{ }
int main() {
f(GetE<float>::type);
return 0;
}
,因为f
需要一个(const)引用,所以不能立即应用左值到右值的转换,因此这构成了异常使用。编译器会报错它缺少一个定义。
(备注。正如ShafikYaghmour所发现的(请参阅注释),如果编译器使用优化,您可能不会收到投诉,因为引用可能会被优化掉。要重现编译器报错,请使用-O0
标志(或类似标志,取决于编译器)。
要解决这个问题,可以用通常的方式提供所需的定义,即在结构定义之外:
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;
可能是因为您忘记在enum定义后放置分号,这在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
相关文章:
- 如何在没有映射的情况下在枚举和字符串之间进行转换?
- std::映射键作为模板化结构与枚举成员
- 如何使用枚举将字符值映射到 int
- 编译结构的时枚举映射
- 有效的双向作用域枚举映射
- 映射枚举值为C 中的模板参数
- 使用 C++11 可变参数模板初始化枚举到字符串映射
- 将枚举值映射到 C++ 中的类型
- 将C++枚举映射为常量字符*
- 在类中映射命名空间枚举
- 将一个枚举映射到另一个枚举
- 定义基于模板的映射指针,以便在验证范围时将 int 解析为枚举
- 在C++中如何将运行时类型鉴别器映射到模板实例(无需手动枚举所有实例)
- 枚举映射对重构具有鲁棒性
- 在模板专门化中映射枚举
- 使用C++中的函数指针映射枚举键和值
- 映射/联接两个自动生成的枚举的最佳方式
- 将存储在多映射中的私有枚举作为值读取
- 我如何消除这个枚举到字符串映射代码的样板文件?
- 无法访问常量静态标准::映射枚举结构