Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do `using` of weak enums in C++11?

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?

like image 862
abyss.7 Avatar asked Mar 21 '23 17:03

abyss.7


2 Answers

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;
}
like image 148
dyp Avatar answered Mar 29 '23 23:03

dyp


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
like image 42
BЈовић Avatar answered Mar 30 '23 00:03

BЈовић