473,670 Members | 2,518 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Query regarding enums in switch/case statements.

Hi. I have a c++ project that is basically a set of implementation
hiding classes, so that we can convert a static lib with a lot of
dependancies into a dynamic lib with less dependancies, so that users
of the lib dont require all the development tools we used to develop
the lib.

I have noticed something strange, and was wondering if its a C++
feature, or a implementation specific bug.

I have a function like this:

CheckerErrorId CCheckerError:: GetErrorId()
{
ECheckerError ce = pimpl->getC_ErrorId() ;
switch (ce)
{
case CINFO:
return CINFO;
case CHWARNING_bus_b locked_yet:
return CHWARNING_bus_b locked_yet;
case CHWARNING_no_ou tput_message_de fined:
return CHWARNING_no_ou tput_message_de fined;
// Rest of list omitted.
default:
return CHERROR_unknown ;
}
}

This function converts the internally used ECheckerError enum (as
defined in the original static libs header files) into the equivalent
CheckerErrorId as defined in my dynamic lib.

However the compiler seems to treat ce as if it were a CheckerErrorId
rather than a ECheckerError. pimpl->getC_ErrorId () could return CINFO,
but the switch statement seems to skip to the case that CINFO matches
in the list of Checker.

Internal enum looks something like this (most of it removed):

enum ECheckerError {
CHERROR_unknown ,
CHWARNING_bus_b locked_yet,
CHWARNING_no_ou tput_message_de fined,
CINFO
};

CheckerErrorId looks like :
enum CheckerErrorId {
CHERROR_unknown ,
CHWARNING_bus_b locked_yet,
CHWARNING_bus_u ndefined,
CHWARNING_no_ou tput_message_de fined,
TPCHWARNING_wro ng_generalTimeo ut_time,
CINFO
};

So if pimpl->getC_ErrorId () returns CINFO, then it jumps down to the
case for CHWARNING_no_ou tput_message_de fined.

If we use if and == then the problem remains. The compiler seems to
ignore the fact that ce is a ECheckerError, and treats it like it were
a CheckerErrorId, or perhaps as if they were merely #defines or
something, simply replacing them by their integer representations !

My question is, is this standard c++ behavior or a possible compiler
bug?

Thanks a lot gurus.

Kurt

Mar 23 '07 #1
7 5257
On Mar 23, 9:23 am, "Kurt" <kurt.haeus...@ gmail.comwrote:
Hi. I have a c++ project that is basically a set of implementation
hiding classes, so that we can convert a static lib with a lot of
dependancies into a dynamic lib with less dependancies, so that users
of the lib dont require all the development tools we used to develop
the lib.

I have noticed something strange, and was wondering if its a C++
feature, or a implementation specific bug.

I have a function like this:

CheckerErrorId CCheckerError:: GetErrorId()
{
ECheckerError ce = pimpl->getC_ErrorId() ;
switch (ce)
{
case CINFO:
return CINFO;
case CHWARNING_bus_b locked_yet:
return CHWARNING_bus_b locked_yet;
case CHWARNING_no_ou tput_message_de fined:
return CHWARNING_no_ou tput_message_de fined;
// Rest of list omitted.
default:
return CHERROR_unknown ;
}

}

This function converts the internally used ECheckerError enum (as
defined in the original static libs header files) into the equivalent
CheckerErrorId as defined in my dynamic lib.

However the compiler seems to treat ce as if it were a CheckerErrorId
rather than a ECheckerError. pimpl->getC_ErrorId () could return CINFO,
but the switch statement seems to skip to the case that CINFO matches
in the list of Checker.

Internal enum looks something like this (most of it removed):

enum ECheckerError {
CHERROR_unknown ,
CHWARNING_bus_b locked_yet,
CHWARNING_no_ou tput_message_de fined,
CINFO

};

CheckerErrorId looks like :
enum CheckerErrorId {
CHERROR_unknown ,
CHWARNING_bus_b locked_yet,
CHWARNING_bus_u ndefined,
CHWARNING_no_ou tput_message_de fined,
TPCHWARNING_wro ng_generalTimeo ut_time,
CINFO

};

So if pimpl->getC_ErrorId () returns CINFO, then it jumps down to the
case for CHWARNING_no_ou tput_message_de fined.

If we use if and == then the problem remains. The compiler seems to
ignore the fact that ce is a ECheckerError, and treats it like it were
a CheckerErrorId, or perhaps as if they were merely #defines or
something, simply replacing them by their integer representations !

My question is, is this standard c++ behavior or a possible compiler
bug?
Obviously you can't have two enum constants with the same name in the
same scope. So, for instance:

enum E1 { A };
struct S
{
enum E2 { A }; // Ok: different scope
};
enum E3 { A }; // Error: A already exists in this scope

In your function since the compiler would complain if your return
value type wasn't convertible to a CheckerErrorId, apparently the enum
constants for CheckerErrorId are in scope but those for ECheckerError
are not (but then how is the enum type ECheckerError unqualified? Is
that your real code or did you [incorrectly] modify it for this
post?).

Please clarify, and check out this FAQ on posting code that doesn't
work properly:

http://www.parashift.com/c++-faq-lit...t.html#faq-5.8

Cheers! --M

Mar 23 '07 #2
On Mar 23, 2:44 pm, "mlimber" <mlim...@gmail. comwrote:
Obviously you can't have two enum constants with the same name in the
same scope. So, for instance:

enum E1 { A };
struct S
{
enum E2 { A }; // Ok: different scope
};
enum E3 { A }; // Error: A already exists in this scope

In your function since the compiler would complain if your return
value type wasn't convertible to a CheckerErrorId, apparently the enum
constants for CheckerErrorId are in scope but those for ECheckerError
are not (but then how is the enum type ECheckerError unqualified? Is
that your real code or did you [incorrectly] modify it for this
post?).

Please clarify, and check out this FAQ on posting code that doesn't
work properly:
Thanks a lot for the fast response. Thats the real code, except I have
taken out most of the enum entries. As far as scope goes,
CheckerErrorId is defined in a namespace, ECheckerError not, but I
think they are both in scope. Seems like at compile time theres no
issue, why should the compiler expect ECheckerError to be convertible
to a CheckerErrorId? Theres no explicit assignment or comparison
between the two.

Surely the type safety mechanism makes it clear that the only thing
following the case can be a ECheckerError, and the only things that
can be returned are CheckerErrorIds ?

The issue only really appears at run time, when the type of ce seems
to be ignored.

Or perhaps the error is that my compiler neglects to detect any scope
collision.

Ahh it is the namespace thing isnt it. If I am "using" the namespace,
then the ECheckerError enums should be preceeded by a :: right? Heh
amazing how typing out a newsgroup article helps one think things
over.

But still... Typesafety should have provided the compiler and/or
runtime system with sufficient information to distinguish which is
which.. ce is declared as a ECheckerError, the compiler shouldnt even
consider that anything following a case statement is anything else.

Mar 23 '07 #3
On Mar 23, 10:10 am, "Kurt" <kurt.haeus...@ gmail.comwrote:
On Mar 23, 2:44 pm, "mlimber" <mlim...@gmail. comwrote:
Obviously you can't have two enum constants with the same name in the
same scope. So, for instance:
enum E1 { A };
struct S
{
enum E2 { A }; // Ok: different scope
};
enum E3 { A }; // Error: A already exists in this scope
In your function since the compiler would complain if your return
value type wasn't convertible to a CheckerErrorId, apparently the enum
constants for CheckerErrorId are in scope but those for ECheckerError
are not (but then how is the enum type ECheckerError unqualified? Is
that your real code or did you [incorrectly] modify it for this
post?).
Please clarify, and check out this FAQ on posting code that doesn't
work properly:

Thanks a lot for the fast response. Thats the real code, except I have
taken out most of the enum entries. As far as scope goes,
CheckerErrorId is defined in a namespace, ECheckerError not, but I
think they are both in scope. Seems like at compile time theres no
issue, why should the compiler expect ECheckerError to be convertible
to a CheckerErrorId? Theres no explicit assignment or comparison
between the two.

Surely the type safety mechanism makes it clear that the only thing
following the case can be a ECheckerError, and the only things that
can be returned are CheckerErrorIds ?

The issue only really appears at run time, when the type of ce seems
to be ignored.

Or perhaps the error is that my compiler neglects to detect any scope
collision.

Ahh it is the namespace thing isnt it. If I am "using" the namespace,
then the ECheckerError enums should be preceeded by a :: right? Heh
amazing how typing out a newsgroup article helps one think things
over.

But still... Typesafety should have provided the compiler and/or
runtime system with sufficient information to distinguish which is
which.. ce is declared as a ECheckerError, the compiler shouldnt even
consider that anything following a case statement is anything else.
Does your compiler allow this:

enum E1 { A };
namespace NS { enum E2 { A }; }
using namespace NS;

It shouldn't because A is ambiguous. Hence, I don't think you've
assessed your scope problem correctly. Please post a *complete* but
*minimal* sample (i.e., one that we can cut and paste into our editors
unchanged) that demonstrates your problem.

In any case, this should work fine:

enum E1 { A, B };
namespace NS { enum E2 { A, B }; }

NS::E2 Foo( E1 e1 )
{
switch( e1 )
{
case NS::A: // Not ::A
return NS::A;
default:
return NS::B;
}
}

The reason is that enums are convertible to and therefore comparable
as ints, so the compiler won't complain about the type in such a
switch statement. See also:

http://www.parashift.com/c++-faq-lit...html#faq-29.19
http://www.parashift.com/c++-faq-lit...html#faq-29.20

Cheers! --M

Mar 23 '07 #4
On Mar 23, 3:49 pm, "mlimber" <mlim...@gmail. comwrote:
Does your compiler allow this:

enum E1 { A };
namespace NS { enum E2 { A }; }
using namespace NS;

It shouldn't because A is ambiguous. Hence, I don't think you've
assessed your scope problem correctly. Please post a *complete* but
*minimal* sample (i.e., one that we can cut and paste into our editors
unchanged) that demonstrates your problem.
Heh my compiler has no problem at all with it. (MS VC++ 2005 without
the buggy SP1)

However when I do something like:

enum E1 { C, A, B };
namespace NS { enum E2 { A, B, C, D, E }; }
using namespace NS;

E2 Foo( E1 e1 )
{
switch( e1 )
{
case A:
return A;
default:
return B;
}
}

Which is almost analogous to my situation, then I get ambiguous symbol
errors. Still trying to work out exactly why my real code doesnt
generate this error...

Anyway, it was no real problem, I just renamed all the entries in my
CheckerErrorId by prefixing them with something so they dont clash
with the ECheckerError.

Thanks a lot for your comments.

OK! Now I have the analagous example: The difference was that Foo is a
member of a class.

enum E1 { C, A, B };
namespace NS { enum E2 { A, B, C, D, E };
class Bar
{
virtual E2 Foo( E1 e1);
};
}
using namespace NS;

E2 Bar::Foo( E1 e1 )
{
switch( e1 )
{
case A:
return A;
default:
return B;
}
}

This compiles fine for me, with no ambiguous symbol errors. Compiler
bug?

Mar 23 '07 #5
enum E1 { C, A, B };
namespace NS { enum E2 { A, B, C, D, E };
class Bar
{
virtual E2 Foo( E1 e1);
};}

using namespace NS;

E2 Bar::Foo( E1 e1 )
{
switch( e1 )
{
case A:
return A;
default:
return B;
}
}

This compiles fine for me, with no ambiguous symbol errors. Compiler
bug?
Hmm GCC on linux has no problem with it either, what difference here
does making Foo a class member make?

Not really trying to solve any problems here as much as just improve
my understanding of c++.

Mar 23 '07 #6
Kurt wrote:
>enum E1 { C, A, B };
namespace NS { enum E2 { A, B, C, D, E };
class Bar
{
virtual E2 Foo( E1 e1);
};}

using namespace NS;

E2 Bar::Foo( E1 e1 )
{
switch( e1 )
{
case A:
return A;
default:
return B;
}
}

This compiles fine for me, with no ambiguous symbol errors. Compiler
bug?

Hmm GCC on linux has no problem with it either, what difference here
does making Foo a class member make?

Not really trying to solve any problems here as much as just improve
my understanding of c++.
Actually, the difference is that Foo is (indirectly) enclosed by
the namespace NS, causing a lookup for the enumerator constants A
and B from *within* the namespace (more precisely, from a subscope
within that namespace).

As E2 is defined within the namespace its enumerators shadow
identically named enumerators in namespaces (including the global
namespace) enclosing NS.

Mar 23 '07 #7
On Mar 23, 11:32 am, "Kurt" <kurt.haeus...@ gmail.comwrote:
On Mar 23, 3:49 pm, "mlimber" <mlim...@gmail. comwrote:
Does your compiler allow this:
enum E1 { A };
namespace NS { enum E2 { A }; }
using namespace NS;
It shouldn't because A is ambiguous. Hence, I don't think you've
assessed your scope problem correctly. Please post a *complete* but
*minimal* sample (i.e., one that we can cut and paste into our editors
unchanged) that demonstrates your problem.

Heh my compiler has no problem at all with it. (MS VC++ 2005 without
the buggy SP1)
Mea culpa. I should have added a use of A after it, like:

int main()
{
return A;
}

Now Comeau, VC++ '05, EDG, and gcc give an error.
OK! Now I have the analagous example: The difference was that Foo is a
member of a class.

enum E1 { C, A, B };
namespace NS { enum E2 { A, B, C, D, E };
class Bar
{
virtual E2 Foo( E1 e1);
};}

using namespace NS;

E2 Bar::Foo( E1 e1 )
{
switch( e1 )
{
case A:
return A;
default:
return B;
}
}

This compiles fine for me, with no ambiguous symbol errors. Compiler
bug?
Ok, now we're down to the real problem. As Michael Mehlich said, the
issue is not that Foo is a member function but that Foo is in the same
namespace with E2, which silently hides E1's constants since their
outside the namespace. (PC-Lint by Gimpel catches things like this,
BTW. You might want to check it out.) And like I said previously,
there's no type error here because e1 is compared *as an int* against
the *integer values* of E2's A and B but the proper enum type is still
returned.

Cheers! --M

Mar 23 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2284
by: wiredog | last post by:
I am struggling rewriting my query from MS Access' IIF, Then to SQL Servers TSQL language. I am hoping some one can give me some guidance. I believe I have the first portion of the query correct but do believe this requires a "NESTED" argument. This is where I am lost. My Original MS ACCESS Query reads-- SELECT DISTINCTROW REGION_TRAFIC.*, IIf(Mid(,5,2)=,
27
2726
by: Mark A. Gibbs | last post by:
i have been toying with the idea of making my enums smarter - ie, more in line with the rest of the language. i haven't tested it yet, but what i came up with is a template like this: template <typename Enum> class smart_enum { public: typedef Enum enum_type;
10
9573
by: clueless_google | last post by:
hello. i've been beating my head against a wall over this for too long. setting the variables 'z' or 'y' to differing numbers, the following 'if/else' code snippet works fine; however, the 'case' code snippet does not. (the code's function is illustrative.) ////////////////////////////////////////// //////// working 'if/else' switch //////// //////////////////////////////////////////
17
2811
by: prafulla | last post by:
Hi all, I don't have a copy of C standard at hand and so anyone of you can help me. I have always wondered how switch statements are so efficient in jumping to the right case (if any)? Can anybody point me to the innards of it please? Sorry if this is OT on clc and more relevant to comp.compilers. I am confused here too.
2
2877
by: Simon Elliott | last post by:
I have some legacy C++ code which requires some enums to be 1 or 2 bytes in size. I'd ideally like to be able to specify that a few carefully selected enums are a particular size. By default, g++ seems to create enums of 4 bytes in length, unless I use the -fshort-enums option. I don't much want to use this all or nothing approach in case it breaks library code etc, and there's no guarantee that other compilers have a comparable...
1
284
by: MariuszC | last post by:
Hello, I have used some library where is defined enum like: typedef enum Enum1 { ENUM1_1, ENUM1_2, ENUM1_3, ENUM1_4, ENUM1_5 }; In my code I have defined: typedef enum Enum2 { ENUM2_1, ENUM2_2, ENUM2_3, ENUM2_4, ENUM2_5 }; My map function looks like:
7
2196
by: alunharford | last post by:
When I'm coding in Java, I might write the following (contrived) code: boolean b = SomeMethod(); switch (b) { case true: return 1; case false: return 0; default: throw new InternalError();
5
4745
by: sam_cit | last post by:
Hi Everyone, I read somewhere that there are some compile time operations behind switch-case, which is why it can work for cases which evaluates to an integer or character and not strings and that it makes switch-case faster than if-else statements, is it true and if so what is the underlying concept behind a switch-case compilation? Can anyone help in this regard. Thanks in advance!!!
10
9594
by: =?utf-8?b?QXNiasO4cm4gU8OmYsO4?= | last post by:
I came over this code which puzzled me. Isn't the enum supposed to have an identifier? enum { BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ BT_OPEN, BT_BOUND, BT_LISTEN, BT_CONNECT, BT_CONNECT2,
0
8466
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8384
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8810
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8659
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7410
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5683
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4208
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4387
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2798
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.