Archived

This topic is now archived and is closed to further replies.

AndreTheGiant

switch on enumeration should be warning?

Recommended Posts

Hi, In Stroustrup's book, (page 77), he says that if you switch on an enumeration, then the compiler can issue a warning if for example you miss one of the values. If I understand that right, then in the following code,
enum CONSTANTS {FRONT, BACK, ON};        
CONSTANTS side = pla.vertSide(testV1);
switch(side) {
case FRONT: cout<<"front"<<endl; break;
case BACK: cout<<"back"<<endl; break;
}
the compiler *should* issue a warning that I forgot to handle the ON value right? Acutally, i know compilers dont *have* to give a warning if they dont want to, but seeing as how im using msvc++ 6.0, and its pretty snazzy, I thought that it might. Am I doing something wrong, or does msvc++ just not warn about this? thanks! [edited by - AndreTheGiant on July 25, 2003 11:31:49 PM]

Share this post


Link to post
Share on other sites
Such a warning would be annoying. I can think of a half-dozen scenarios in which not all enumeration values would be meaningful within a switch statement.

Just get in the habit of using assertions; it''s more robust anyway (since you might have to handle an out-of-range enumeration, which the compiler couldn''t flag):

switch(xxx)
{
case ABC:
// blah
break;

case DEF:
// blah
break;

default:
ASSERT(false);
}



How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites
I''ve never used MSVC++, but I know that in gcc some warnings have to be turned on and some warnings only work when optimization is turned on as well. Both might be things to look in to. Another thing is, if you have a default: case in your switch, then it shouldn''t be issuing a warning because you are covering all cases.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You might have to turn on all warnings: -Wall in gcc(I think) and an option in project settings in msvc++.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Promit
Warning: Warning Level 4 gives you a lot of complete bullshit.


I disagree with that statement. If you always write code to cope with W4 you will avoid many bugs.

I''ve worked as a contractor helping to fix systems that don''t work well (performance problems, memory/resource leaks, crashes etc.). I''ve seen the most stupid bugs that easily could have been avoided if people only did 2 things:
- Build their code with W4 and "break on errors"
- Never ever ignore return values (from CloseHandle etc.)

With VC6 and earlier it''s been tough to do this as the windows headers and STL haven''t built clean on W4. With VS.Net they do, which is a really good thing. Treat /W4 and /WX as your friends as they will help you to find bugs.

If you know a certain warning is harmless (such as a for loop where you compare some unsigned value with the signed "int i" fix the problem instead of having a warning around. Change "i" to size_t (or whatever unsigned type you''re comparing with.
In some cases you can choose to #pragma warnings away if needed and you know it''s ok to do so. Just don''t ignore the warnings, they are there for a reason.

Share this post


Link to post
Share on other sites
quote:
Original post by Promit
Try going to warning level 4 and see what it says.

Warning: Warning Level 4 gives you a lot of complete bullshit.


You can use W4 and turn off the useless warnings with

#pragma warning ( disable: nnnn )

Share this post


Link to post
Share on other sites
Speaking of warning level 4...

Does anyone know of a way to get only code we write to use warning level 4 and the other headers (from libs, etc.) to use W3 or something?

I really could give a rat’s backside less about *some other person’s* flaky code if I can’t change it! (once I know about it that is...)

Tanks
Feral

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
From visual studio, open project settings, select all configurations and change to W4. Then select only your precompiled file (stdafx.cpp) and set that to W4.
You could also use #pragma warning(push, 3) first in stdafx and #pragma warning(pop) in the end.


Make sure to include all external header files from stdafx.h. Your own cpp files should first include stdafx.h, then your header files needed. Never include external headers from any other place than stdafx.h.

VC6 isn''t too god in handling this, VS.Net is much better.

Your header files should in my opinion not include any other files, instead the cpp files should include what is neeed. Other people will probably have opionions about this, but that''s what I use and like. My header files never have any #include statements.

Share this post


Link to post
Share on other sites
quote:

Your header files should in my opinion not include any other files, instead the cpp files should include what is neeed. Other people will probably have opionions about this, but that''s what I use and like. My header files never have any #include statements.



I agree in general that it''s good to avoid #includeing in headers if you can avoid it but it''s not always possible to avoid it. What if you want to inherit from a class defined in another header? Or have a member of a type defined in another header? I don''t see how you can code C++ without sometimes including a header in another header. You might be able to do it if you''re just coding in straight C I suppose.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Anonymous Poster
...and set that to W4.
Of course I meant to write "...and set that to W3", but I guess you understood that...

Mattnewport, it''s possible to as I said. Suppose you have classes CBase and CDerived in base.h/cpp and derived.h/cpp, and use them from main.cpp.

base.cpp must (obviously) include base.h
derived.cpp must include base.h and derived.h (in that order).
Your main.cpp must include base.h and derived.h (in that order).

There are certainly disadvantages with doing as I prefer, but overall I think I get a cleaner solution. The main advantage is when having classes exported from dlls and other projects using those. I think it''s easier to separate the private headers for a certain dll, and the public headers that I need to ship.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
"Your main.cpp must include base.h and derived.h (in that order)"

Not only your main.cpp but any other module that wants to use that class would have to do that.
As all the code *must* be there, you''re just forcing yourself to remember in what order to include the headers. If there would be any scenario where you could sensibly use derived.h without the information of base.h, one could agree with you. But, as said, you just move the #include statement and force yourself to remember how to include your headers. Worse, you force any client programmer to do the same.

Share this post


Link to post
Share on other sites
quote:

Mattnewport, it''s possible to as I said. Suppose you have classes CBase and CDerived in base.h/cpp and derived.h/cpp, and use them from main.cpp.

base.cpp must (obviously) include base.h
derived.cpp must include base.h and derived.h (in that order).
Your main.cpp must include base.h and derived.h (in that order).



You''re right. I''ve adopted some of the design rules from ''Large Scale C++ Software Design'' and have been using them for a while now so I''d forgotten that you don''t actually have to do things the way it suggests... One of the design rules is that the .c/.cpp file of a component should include it''s own .h file as the first substantive line of code. This ensures that the .h file will compile without requiring the .cpp file it is included in to include certain other .h files before it in a particular order.

I think it''s bad design to require someone including a .h file to include all the other .h files required to get that .h to compile in some particular order. Say you change the private implementation of a class foo to use std::strings instead of character arrays and as a result have to #include <string> in order to compile the class definition (because it has a private string member replacing a private char* or char array). That''s purely an implementation change and should only require other files using the class to be recompiled. If the .h does not include all the .hs on which it depends then all the files that use the class will have to be edited to #include <string> before they #include "foo.h".

In my opinion someone wishing to use a class you have written from another file (even if that someone is usually you) should be able to do so simply by #including the header file for that class. They should not have to include some arbitrary number of other header files in a particular order to use your class. Unless you document exactly which header files need to be included (and since the compiler doesn''t automatically check your documentation it will get out of date) then the poor programmer will have to waste time figuring out which header files he needs to include and which he can do without by looking at the corresponding .cpp file. I also think that it should be possible to use the class regardless of where in the ordering of #include directives the .h file appears. I think these concerns outweigh any benefits that might be gained from not #including any .h files in other .h files.

Share this post


Link to post
Share on other sites