Reputation: 1256
I recently produced a wierd set of errors when working on a little project. This was basically the code that caused it:
#include <memory>
enum derivedtype {B, C};
//abstract class
class A{};
class B : public A
{};
class C : public A
{};
int main()
{
{
std::unique_ptr<A> myb(new B);
std::unique_ptr<A> myc(new C);
}
}
Which produces this compiler error:
enumclasserror.cpp: In function ‘int main()’:
enumclasserror.cpp:15:30: error: ‘B’ does not name a type
std::unique_ptr<A> myb(new B);
^
enumclasserror.cpp:16:30: error: ‘C’ does not name a type
std::unique_ptr<A> myc(new C);
The fix was adding the class keyword after the new:
std::unique_ptr<A> myb(new class B);
Now the enum was included in the headerfile of the abstact class in the original code(which made it even harder to spot), but nevermind that; I could have never imagined that the members of an enum can cause the creation of an instance to fail. It literally took me hours to find that bug. Can anyone explain to me why that happens? Does new make any sense with enums?
P.S.: The error was found by a collegue who uses clang which suggested the class keyword. The standard c++ compiler on my Ubuntu, as you can see, didn't tho..
Upvotes: 0
Views: 1900
Reputation: 726559
In your example B
from enum
hides class B
. Section 3.3.10 of the standard describes the rules for name hiding:
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
Language designers needed to set precedence rules, so they decided that enum
constant name should win. This rule seems arbitrary, and is probably modeled after some old rule in the C standard. However, it is part of the standard, so every compiler must comply with it.
It goes without saying that making a class name collide with an enum
member is a very bad idea. The best solution to this problem is renaming your class.
Upvotes: 5
Reputation: 385144
I'm not sure what else you expected here.
First, you introduced integral constants named B
and C
. Of course, you cannot new
these. That would be like writing new 42
.
Then, you introduced types with the same names. Okay, fine, that's allowed, but in order to use these you must now refer to them as class B
and class C
(or struct B
and struct C
), as you've discovered.
Do not use the same name for different things.
Upvotes: 2