如何在C++11中使用弱枚举(weak enums)?

4
我在头文件中的类里定义了一个枚举:
namespace A {

class B {
 public:
  enum Value {
    VALUE1 = 1,
    VALUE2 = 2,
  };
};

}

我希望在源文件中无需前缀地使用它的值,就像这样:

#include "header"

int main() {
  someFn(VALUE1);

  return 0;
}

我尝试使用A::B::Value;,但是clang报错:

using声明不能引用类成员


即使我将枚举移动到类外:

namespace A {

enum Value {
  VALUE1 = 1,
  VALUE2 = 2,
};    

}

当使用 using A::Value; 时,错误消失了,但编译器会抱怨 VALUE1

使用未声明的标识符'VALUE1'

如果枚举在其他地方定义,有没有一种方法可以不使用任何前缀来使用枚举的值? - 使用#define是不可能的。
如果没有办法,那么在C++标准中实现这种行为可能会出现什么问题?
4个回答

4

你的方法失败有两个原因:

  1. The first reason has been described by BЈовић: You cannot introduce the name of a nested type in a namespace scope, see [namespace.udecl]/8.

  2. When you write using A::B::Value;, only the name of the enum itself will be introduced in the current scope, not the name of all enumerators. This allows things like:

    namespace Values { enum Value{ VALUE1, VALUE2 }; }
    using Values::Value;  // don't pollute my scope with the enumerators
    
    Value v = Values::VALUE1;
    
第二个问题可以通过单独引入枚举来解决:
namespace A
{
    namespace B
    {
        enum Value
        {
              VALUE1
            , VALUE2
        };
    }
}

int main()
{
    using A::B::Value;
    using A::B::VALUE1;
    using A::B::VALUE2;

    Value v = VALUE1;
    v = VALUE2;
}

另外,正如hvd评论中建议的那样,您可以使用using指令引入命名空间的所有名称:

namespace A
{
    namespace B
    {
        enum Value
        {
              VALUE1
            , VALUE2
        };
    }
}

int main()
{
    using namespace A::B;

    Value v = VALUE1;
    v = VALUE2;
}

3
简而言之:这是不可能的,因为枚举类型是在类内定义的。
如果您将 class B 改成 namespace B
namespace A {

namespace B {
  enum Value {
    VALUE1 = 1,
    VALUE2 = 2,
  };
};

}

如果你按照你的代码所写,那么就有可能实现以下操作:

using A::B::Value

1
但是,正如我之前所提到的,编译器(clang)会报错:使用未声明的标识符 'VALUE1' - abyss.7
@abyss.7 这很奇怪。你应该会得到“错误:‘A::B’不是一个命名空间”。 - BЈовић
@abyss.7 实际上,它告诉你我在答案中写的内容。我写的错误信息来自g++。 - BЈовић
即使错误信息不同,这对我们两个来说仍然无法正常工作。 - abyss.7
2
@abyss.7 在你的问题中,你写道“并且使用using A::Value;”,不要这样做。不要仅导入Value名称。导入整个命名空间,并确保该命名空间仅用于该枚举。 - user743382

0

枚举类型的处理方式类似于类。可以将其视为尝试执行以下操作:

class Value
{
public:
    static const int VALUE1 = 0;
};

using Value::VALUE1; // ERROR class-qualified name

简而言之:您无法通过using语句以这种方式使枚举值可见。

0

嗯,我能想到的最接近的是:

namespace A {
  class B {
  public:
    enum Value { VALUE1 = 1, VALUE2 = 2 };
  };
};

const A::B::Value VALUE1 = A::B::VALUE1;

int main () {
  return VALUE1;
}

但这相当繁琐且容易出错,绝对不值得。 :)


这不是一个好的做法,因为我必须在每个想要使用它们的地方重复所有枚举值。 - abyss.7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接