Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use class and enum with same name?

Tags:

c++

enums

class

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
        }
    };
};
like image 542
cairol Avatar asked Feb 12 '10 09:02

cairol


2 Answers

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).

like image 60
David Rodríguez - dribeas Avatar answered Nov 18 '22 18:11

David Rodríguez - dribeas


 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.

like image 24
AProgrammer Avatar answered Nov 18 '22 18:11

AProgrammer