Reputation: 8773
I've a class and an enum value which have the same name. Inside the class I want to use the enum which gives an error. Is there any way to use the enum without renaming or moving to a different namespace?
Example:
namespace foo {
enum bar {
BAD
};
class BAD {
void worse () {
bar b = BAD; // error
}
};
};
Upvotes: 12
Views: 8754
Reputation: 52284
bar b = foo::BAD;
or if you are in the global namespace
bar b = ::BAD;
but that name overloading is not something I'd recommend. C++0X will allow
bar b = bar::BAD;
which is a better solution if the dependency on C++0X is acceptable.
As promised, the explanation
9.1/2
If a class name is declared in a scope where an object, function, or enumerator of the same name is also declared, then both declarations are in scope, the class can be referred to only using an elaborated-type-specifier (3.4.4)
The elaborated-type-specifier is the form
class BAD b;
This is for compatibility with C where tag names are in a different name space and must be [i]typedef[/i]ed if one want to use them without an elaborated-type-specifier. (A well known example with a function is the struct stat and the function stat in Unix).
That explain why the overloading of a name to designate a class and an enumerator is possible. The reason for which BAD designate the class here is that the name of the class is also defined into the class scope and in a member function definition the scope searched are in order: - the member function scope - the class scope - the namespace containing the class definition
BAD is found at class scope, so the namespace foo is never searched.
Upvotes: 5
Reputation: 208353
This is one of those tricky parts of how the name lookup is performed.
There are two identifier scopes in C++, one for class types and general identifier scope. The enum value BAD resides in the general identifier scope, while the class type BAR resides in the class identifier scope. That is the reason why you are allowed to have both an enum value and a class with the same name: both names do not collide.
Within class BAD, the identifier lookup rules will find the class BAD before it finds the enum, and thus the error. Now, if you fully qualify the identifier then the name lookup will first check the global identifier scope and match the enum value. On the opposite end, you will have to add the struct
or class
keyword to declare variables of type BAD.
namespace foo {
enum bad { BAD; };
class BAD {
void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum
};
}
int main() {
// foo::BAD b; // error, foo::BAD is an enum, not a type
class foo::BAD b; // correct
}
Now, I would advice against this usage. It is generally not a good idea to reuse an identifier like this. Code will be more complex, and probably misleading for the casual reader (the same unqualified identifier refers to different things when used in different contexts). If the names do need to be BAD
, consider using an enclosing namespace or class for either the class or the enum (prefer the enum there).
Upvotes: 10
Reputation: 39354
This works in VS2008, but gives a warning:
bar b = bar::BAD;
Its not something I can recommend.
You should put the enum within another namespace inside foo
and qualify both bar
and BAD
with the new namespace.
Upvotes: 0
Reputation: 11223
No, there is no way to do that. You should use valid identifier. Valid identifier means that you have to be able to identify with it. :)
Upvotes: 0