I want to maintain an existing API that heavily uses an inner enum but I need to separate the enum out into its own type:
This is the current API:
class Outer {
public:
enum Inner {
FIELD1
};
};
In other words, users currently expect to set Inner
s by using Outer::Inner
.
I would like to preserve the name if possible when I make the new outside type:
enum Inner {
FIELD1
};
class Outer {
public:
typedef Inner Inner;
}
However - it gives me a compiler error:
./Playground/file0.cpp:23:19: error: declaration of 'typedef enum Inner Outer::Inner' changes meaning of 'Inner' [-fpermissive]
23 | typedef Inner Inner;
| ^~~~~
./Playground/file0.cpp:17:6: note: 'Inner' declared here as 'enum Inner'
17 | enum Inner {
| ^~~~~
If I just change the name of the enum it all works fine.
#include <cassert>
enum Enum {
FIELD1
};
class Outer {
public:
typedef Enum Inner;
};
int main() {
Enum field = Enum::FIELD1;
Outer::Inner field_alt = Outer::Inner::FIELD1;
assert(field == field_alt);
return 0;
}
This is not allowed because of the rule [basic.scope.class]/3:
A name
N
used in a classS
shall refer to the same declaration in its context and when re-evaluated in the completed scope ofS
. No diagnostic is required for a violation of this rule.
When you do typedef Inner Inner;
, you're violating this rule. The first time Inner
appears on that line, it is a use of the name, and is found to refer to the declaration ::Inner
. But once the class is completely defined, Inner
now refers to the typedef declaration. So the program is ill-formed NDR (GCC is nice enough to give you a diagnostic).
You need to change it to:
typedef ::Inner Inner;
Now, the unqualified name Inner
is not being used anymore; instead you are using the qualified name ::Inner
, and its meaning stays the same after the typedef, so there should be no issue.