C++ C++;11“列举正向原因”;“基础类型不匹配”;

C++ C++;11“列举正向原因”;“基础类型不匹配”;,c++,c++11,gcc,g++,forward-declaration,C++,C++11,Gcc,G++,Forward Declaration,我在C++11中工作,包括一个用C++03实现的h文件。在我包含的h文件中,定义了一个enumFoo。我想在code.h中声明对它的转发,并在code.cpp中使用它: 标题h: enum Foo {A=1}; 代码h: enum Foo : int; // also tried : unsigned int, long, short, unsigned short, char, unsigned char void bar(Foo foo); code.cpp: #include head

我在C++11中工作,包括一个用C++03实现的h文件。在我包含的h文件中,定义了一个enum
Foo
。我想在
code.h
中声明对它的转发,并在
code.cpp
中使用它:

标题h:

enum Foo {A=1};
代码h:

enum Foo : int; // also tried : unsigned int, long, short, unsigned short, char, unsigned char
void bar(Foo foo);
code.cpp:

#include header.h
void bar(Foo foo) { }
这是我编译时遇到的错误(测试了g++4.8.5和g++5.3.1):

如果我将header.h更改为:

enum Foo : int {A=1};
但是我没有头球,也不能改变它。从表面上看,我只需要知道g++对未指定底层类型的枚举使用什么类型,然后在我的转发中使用该类型

:

#包括
#包括
#包括
枚举Foo{A=1};
枚举Foo:未签名;/:std::底层的_type::type也不起作用
int main()
{

std::cout如果在转发声明中为枚举指定了固定的基础类型,则只能对其进行转发声明。此外,枚举的定义必须使用相同的固定基础类型


您的问题是
header.h
中的枚举定义没有底层类型,但后面的forward声明有一个。它们都必须有一个。

似乎没有任何方法可以做到这一点,即使您指定的底层类型与编译器为您的C++03样式
enum
选择的底层类型完全相同>

示例:编译以下代码

enum Foo { A=1 };
cout << typeid(typename std::underlying_type<Foo>::type).name();

这是因为转发声明和“real”
enum
声明都需要具有相同的显式基础类型,即使您设法“猜测”编译器会为您选择什么



tl;dr:如果转发声明和实际声明都明确指定了相同的基础类型,则只能转发声明
enum

从我今天的gcc版本开始,您必须两次定义确切的类型,不仅在转发声明中,而且在定义中:


这对我来说是有效的,编译器是GCC 7.3.0.

,C++标准明确禁止这个(向前声明枚举需要固定的基础类型)。可能还有另一种解决方案,比如将枚举包装到结构中?我认为在C++11中是可能的。由于C++11,您可以向前声明枚举,但这需要修复基础类型(“指定枚举基”),并为每个声明重复相同的基础类型(向前声明或实际声明)。因此,如果无法将基础类型添加到外部标头,则无法(不允许)向前声明此枚举。
std::unsigned_type
告诉您
enum
的底层类型。它对您的enum说了什么?@Yakk,
unsigned
。但是如果我执行
enum Foo:unsigned
,我会得到上面的错误。我开始理解这不起作用,但我看不出它不起作用的任何原因east这应该是可能的:
enum Foo:std::substanding_type::type
。我想说的是,总是有一个底层类型,只是在C++03样式中,它是隐式的。@ytoledano:您要求编译器确定尚未定义的枚举的隐式底层类型。这是不可能的。编译器没有看到de
Foo
的定义,因此,
std::undernative_type::type
是不合法的语法。隐式的底层类型基于
Foo
的定义,它位于一个您没有包含的头中(如果包含了,则没有必要向前声明枚举)。顺便说一句,VisualStudio(不记得是哪个版本)基础类型规范(作为扩展)之间可接受的不匹配。这会导致危险的不匹配,其中枚举的大小在同一个转换单元中不同,甚至会导致错误的代码。我认为在有关底层类型规范的枚举声明之间加强一致性是一个好主意。关于g++(7.4)上面示例代码中的
cout
行未编译。它应该是
std::undernative\u type::type
not
std::undernative\u type\u t::type
#include <iostream>
#include <string>
#include <type_traits>

enum Foo {A=1};
enum Foo : unsigned; // : std::underlying_type<Foo>::type also doesn't work

int main()
{

  std::cout << "Hello, world\n";
}
enum Foo { A=1 };
cout << typeid(typename std::underlying_type<Foo>::type).name();
enum Foo : unsigned int;
void bar(Foo);

enum Foo {A=1};
main.cpp:8:6: error: enumeration previously declared with fixed underlying type
enum Foo {A=1};
     ^
main.cpp:5:6: note: previous declaration is here
enum Foo : unsigned int;
     ^
enum Foo : int;
enum Foo : int {A=1};