reinterpret_cast在枚举类型中出错

13

为什么我不能使用 reinterpret_cast 操作符进行这样的转换?

enum Foo { bar, baz };

void foo(Foo)
{
}

int main()
{
   // foo(0); // error: invalid conversion from 'int' to 'Foo'
   // foo(reinterpret_cast<Foo>(0)); // error: invalid cast from type 'int' to type 'Foo'
   foo(static_cast<Foo>(0)); 
   foo((Foo)0);
}

1
static_cast 是这里正确的操作。 - Travis Gockel
1
为什么它会有效?你认为reinterpret_cast的作用是什么? - R. Martinho Fernandes
我认为reinterpret_cast可以用于所有类型的转换,因为它强制将任何类型转换为另一种类型,并具有此转换的所有副作用。 - FrozenHeart
1
这里有一个很好的解释:https://dev59.com/N3RB5IYBdhLWcg3wn4UL - Joel Rondeau
3个回答

22
我认为reinterpret_cast可以用于所有类型的转换,因为它强制将任何类型转换为另一种类型,并具有此转换的所有副作用。
这是一个常见的误解。可以使用reinterpret_cast执行的转换在标准的5.2.10中明确列出。其中不包括int-to-enumenum-to-int转换:
- 指针到整数类型,只要整数足够大即可容纳 - nullptr_t到整数 - 整数类型或enum到指针 - 函数指针到不同类型的另一个函数指针 - 对象指针到不同类型的另一个对象指针 - nullptr_t到其他指针类型 - 对象或函数的T1的成员指针到不同的T2的成员指针,在这种情况下,T1T2都是对象或函数 reinterpret_cast通常用于告诉编译器:嘿,我知道你认为这个内存区域是一个T,但我希望你将其解释为U(其中TU是不相关的类型)。
还值得注意的是,reinterpret_cast可能会对位产生影响:
5.2.10.3中说明了,reinterpret_cast进行的映射可能与原始值产生不同的表示形式。
C-style转换总是有效的,因为它包括其尝试中的static_cast

4
由于常规枚举底层类型为 int,因此没有必要进行 reinterpret。对于这种情况,静态转换是适当的转换方式。

2
@Rost 这并不是真的。标准保证枚举的底层类型是整数类型,但不一定是int - Drew Dormann
@tenfour 嗯,这是在C++11中添加的。不知道原因。可能是为了允许一些模板技巧? - Rost
1
如果“没有需要重新解释的内容”与正确性有任何关系,那么以下代码将失败:int x = 0; int* p = reinterpret_cast<int*>(&x); - Travis Gockel
2
enumint 的转换不能通过 reinterpret_cast 完成,这与 enum 的底层类型无关。即使是 enum Foo : uint64_t { bar, baz },也仍然不允许使用 reinterpret_cast<int> - Travis Gockel
因为这是不被允许的。C++标准没有定义将“枚举”用“reinterpret_cast”转换为整数类型。 - Travis Gockel
显示剩余4条评论

0
其他答案没有直接点到问题的核心。 尽管使用reinterpret_cast是不好的,但编译失败是因为你不能直接在值上应用reinterpret_cast。 你只能将其应用于指针或引用表达式的转换。 (特别是它不能转换字面常量。)
所以这个可以编译,
enum Foo { bar, baz };

void foo(Foo)
{
}

int main()
{
   // foo(0);
   int zero = 0;
   foo(reinterpret_cast<Foo&>(zero)); // error: invalid cast from type 'int' to type 'Foo'
   foo(static_cast<Foo>(0)); 
   foo((Foo)0);
}

https://godbolt.org/z/x6MP1e5eo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接