在运行时有条件地声明枚举 (C++)

Conditionally Declaring an Enum at Runtime (C++)

我发现了一些与 运行时间检测相关的有趣发现,这些发现引发了一个有趣的问题。如果我想根据条件声明一个全局变量,我可以在预编译期间使用 #ifdefs 轻松地这样做。但是,这会产生不同的二进制文件,我正在寻找一种可以在 运行 时间内实现的解决方案,以便将行为限制为单个二进制文件。

例子

我可以用数组或其他数据类型执行的一个经典示例(注意,这里的数据类型都是 const 并且必须保持不变 - 反映枚举的不可变行为):

原文(编译时):

#ifdef CONDITION
static const int faveNums[] = {......};
#else
static const int faveNums[] = {******};
#endif

修改(运行时间):

static const int conditonalFaveNums[] = {......};
static const int defaultFaveNums[] = {******};

static const int * const faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;

常见陷阱(范围界定):

这是一个常见的陷阱,不会起作用,因为 if/switch 条件是有范围的,因此以后无法引用 - 感谢三元运算符!

if(IsConditionTrue())
{
    static const int faveNums[] = {......};
}
else
{
    static const int faveNums[] = {******};
}

问题

然而,情况似乎随着枚举而改变。让我们尝试 运行 时间解决方案,但这次使用枚举:

enum conditionalFaveNums = {......};
enum defaultFaveNums = {******};

enum faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;

这不会编译。

编译时定义(与第一个示例一样)可以解决这个问题,但是有没有办法通过在 C++ 中有条件地声明全局枚举来在 运行 时解决这个问题?

你不能这样做。要记住的要点:

  1. 变量的值可以根据 运行 时间信息进行不同的初始化。
  2. 类型在编译时必须是 defined/set。

您可以使用

static const int * const faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;

因为那说明 faveNums 将在 运行 时间被初始化,使用 运行 时间信息。

您不能使用

enum faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;

因为它尝试使用 运行 时间信息来定义类型 faveNums

虽然你不能完全按照你的要求去做 - 你的数组和枚举示例之间的区别在于数组只是数据,而枚举是一种类型,类型定义 必须 在编译时可解析 - 也许更有帮助的答案是这是 的事情。

动态数据应该用动态数据结构表示。 std::set 与枚举在概念上非常接近,并提供了许多有用(且高效)的方法,以后可能会派上用场。更好的方法可能是定义一个在编译时列出所有可能值的枚举,然后根据运行时信息动态构建这些值的 set。 (因此该集合是枚举范围的真子集。)