Вопрос

I have enum definition inside a class in the header:

namespace A {

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

}

And I want to use its values in a source file without prefix, like this:

#include "header"

int main() {
  someFn(VALUE1);

  return 0;
}

I have tried to using A::B::Value; but clang gives an error:

using declaration can not refer to class member


Even if I move enum outside of a class:

namespace A {

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

}

and do using A::Value;, the error is gone, but the compiler complains about VALUE1:

use of undeclared identifier 'VALUE1'

Is there way to use values of enum without any prefixes, if the enum is defined somewhere else? - Using #defines is out of question.

If there is no way, then what is a possible issue about implementing such behavior in C++ Standard?

Это было полезно?

Решение

There are two reasons why your approaches fail:

  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;
    

The second issue can be solved by introducing the enumerators individually:

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;
}

Alternatively, as hvd suggested in a comment, you can use a using-directive to introduce all names of a namespace:

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

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

    Value v = VALUE1;
    v = VALUE2;
}

Другие советы

To put is simply : it is not possible, because enum is defined in the class.

If you change the class B into namespace B:

namespace A {

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

}

then it would be possible to do (as you wrote in your code):

using A::B::Value

Enums are treated in a manner similar to classes. Think of it as trying to do the following:

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

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

In short: You can't make enum values visible this way with a using statement.

Well, the closest I can think of is:

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

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

int main () {
  return VALUE1;
}

but its rather tedious and error prone and absolutely not worth it. :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top