转发声明C ++代码中使用的C头中的枚举?

时间:2017-08-24 02:51:58

标签: c++ c

你不能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>

3 个答案:

答案 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