你不能forward declare an enum in C++但你可以在C.
对于使用某些C ++代码的C代码库,有没有办法在C中使用前向声明的枚举,当在C ++中使用该头时(extern "C" {..}
块内)不会导致错误?
示例:
extern "C" {
enum MyEnum;
}
int main() { return 0; }
GCC给出错误:
error: use of enum ‘MyEnum’ without previous declaration
enum MyEnum;
^~~~~~
Clang也失败了:
error: ISO C++ forbids forward references to 'enum' types
enum MyEnum;
为了给出一些上下文,这是一个主要的C代码库,其中一个小的C ++模块碰巧包含C代码的头。我可以做一些破解让C ++忽略枚举,但想知道在这种情况下C ++是否可以使用C头。
更新:已经注意到官方C规范不支持这一点,但它似乎是一些最广泛使用的编译器中的事实上的标准:GCC / CLANG / MSVC。< / p>
答案 0 :(得分:4)
在C中转发枚举是没有意义的。 C中的枚举仅引入整数枚举常量。它们不会引入您想要使用的任何类型。每个枚举类型都是未指定的整数类型,与所有其他整数类型兼容,因此根本没有类型安全。
typedef enum e12 { ONE, TWO } e12;
typedef enum e34 { THREE, FOUR } e34;
int main () {
e12 one = ONE;
e34 three = THREE;
one = three;
three = ONE;
return one + three;
}
这个C程序在-Wall -Wextra -Wpedantic上用gcc干净地编译。 (当然不会用作C ++程序。)
因此,一个有用的便携式crosss语言解决方案
#ifdef __cplusplus
enum MyEnum : int;
#else
typedef int MyEnum; // 'enum MyEnum' would give no improvement over this
#endif
答案 1 :(得分:2)
您可以从C ++ 11开始在C ++中转发声明枚举。它被称为“不透明声明”而不是“前向声明”,因为从技术上讲它会产生一些不同的效果:枚举的大小在其不透明声明之后是已知的,而前向声明的类型则不是这种情况。
但是,从日常角度来看,它的想法是相同的:您只需声明枚举并在代码中进一步使用它。 From cppreference:
enum-key attr(optional) nested-name-specifier(optional) identifier enum-base(optional) ;(2) (since C++11)
2)不透明枚举声明:定义枚举类型,但不定义其枚举数:在此声明之后,类型是完整类型,其大小已知。注意:类模板的作用域枚举成员的显式特化声明是 nested-name-specifier 出现在标识符之前的唯一情况(自C ++ 14开始)< / p>
答案 2 :(得分:0)
This can be done in C++11,(参见@ vasiliy-galkin的回答),这是一个如何对共享C / C ++标题起作用的例子。
C标头向前声明MyEnum
。
#ifdef __cplusplus
extern "C" {
#endif
enum MyEnum
#ifdef __cplusplus
: int
#endif
;
#ifdef __cplusplus
}
#endif