- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我和一位同事在使用枚举时遇到了一个奇怪的行为。
我们都在使用(大概)相同的 make 文件和相同的编译器 (gcc 4.8.4) 编译同一个项目。唯一的区别是我是一台 Linux 虚拟机,而他在本地 Linux 环境中,但这不应该是问题的根源。
给定以下代码片段
namespace Something
{
enum Something {
DARK_SIDE,
LIGHT_SIDE
}
}
...
Something::Something leEnumVal = Something::Something::DARK_SIDE; // inconsistency here
不一致的是,在我的电脑上出现以下错误:
'Something::Something' is not a class or namespace
但是,在我的同事环境中一切正常。
值得一提的是,我们使用的是QT Creator,在构建过程中可能会产生一些额外的东西。
Ofc,我设法让代码在我的环境中编译,不一致的行变成了:
Something:Something leEnumVal = Something::DARK_SIDE; // this compiles for both
问题 1:处理枚举值的标准方法是什么?
问题 2:什么会导致编译器处理代码的方式不一致? (我的猜测是我的同事在他的设置中使用了一些 C++ 11 特性,但在开始研究他如何启用它们之前我需要一些确认)
上面使用的代码用于显示我们面临的问题。
考虑到这是一个非常大的项目,使用了许多枚举,我们面临这样的情况:一些开发人员使用第一种方法来寻址枚举值,而另一些开发人员则使用第二种方法。
第一种方法的好处是在自动完成期间仅列出来自限定枚举的值,而不是来自整个命名空间的值(例如第二个)。
考虑到命名空间中有许多枚举,所以人们宁愿选择第一种方法也是有道理的。
最佳答案
在 C++11 之前的 C++ 中,枚举不会为其枚举器(常量)生成新的命名空间。您的原始代码行在旧 C++ 中无效,因为没有命名空间 Something::Something
。这是将枚举放在它自己的命名空间中的一个很好的理由:另一种较旧的解决方案是将枚举的名称放在每个枚举器中,例如
enum side {
SIDE_DARK,
SIDE_LIGHT
}
side s = SIDE_DARK;
C++11 引入了scoped enums(又名strong enums),它按照您的原始代码所需的方式工作。要获得完整的强大枚举,您必须使用 enum class
专门请求它:
enum class side {
DARK,
LIGHT,
}
side s = side::DARK;
但为了友好起见,C++11 允许您在使用枚举器名称时使用命名空间表示法,无论您使用的是强枚举还是传统枚举。这支持您的猜测,即您的同事在他的 Makefile 或编译器选项中打开了 C++11,(例如使用 -std=c++0x
或 -std=c++11
)。
MSVC(也许还有其他编译器)有一个非标准扩展,允许您像使用命名空间一样使用枚举,即使在较旧的 C++ 版本中也是如此,所以如果这是 gcc 和 MSVC 之间的区别,那是有道理的,但是您已经在问题中排除了这种可能性。 (我只为 future 的读者提及它。)
由于这是一个大型项目,您应该在您的编码标准或其他项目文档中设置您的目标语言版本。如果您的目标是 C++11,那么您需要更新项目的编译器选项,以便编译原始代码(因为它是有效的 C++11)。如果您的目标是 C++03,任何像您的第一个示例那样编写过代码的人都需要修复它,而不是依赖非标准选项或编译器扩展。
当然,如果您的目标是 C++11,并且不使用强枚举,您可以选择是否将枚举名称用作命名空间。您可能希望在您的编码标准中指定这一点,或者(更好的是)指定应尽可能使用强枚举。
关于c++ - 不一致的完全限定枚举编译时行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33756453/
我是一名优秀的程序员,十分优秀!