WARNING Control reaches end of non-void function c++ - c++

I have following function in C++ code (Its just an example)
Object& XYZ::getObject(InObj obj) {
try{
return obj.getObj();
}
DC_THROW_ERROR(ExceptionObj, "Object Not Found"); // Macro which throws an exception
}
When I compile the above code I get Warning (ie control reaches end of non-void function)..The Macro gets expanded before compilation. So the compiler is aware that if its not returning something its throwing an exception. If so why does compiler gives warning?? These type of functions are evrywhere in my project. To get rid of these warnings i have written below line after the Macro.
return *(static_cast<Object*>(0));
Is it a correct way of fixing it?? I know its bit dodgy.. I can't change the code as for that i have to change around 1000 functions. So can anyone please tell me if there is any better way of fixing it??
Thanks

Listen to the compiler. Get rid of the (so far undisclosed) macro. Or just fix it, but better get rid of it -- you're into the make-C++-look-like-language-X thing, which is ungood.
Cheers & hth.,

Assuming the code in the question is a faithful representation of the code that is causing the problem, the macro DC_THROW_ERROR must be something like
#define DC_THROW_ERROR(err) catch(...) {throw err;}
That semicolon after the DC_THROW_ERROR("Object Not Found") thus results in
Object& XYZ::getObject(InObj obj) {
try {
return obj.getObj();
}
// This is the expansion of DC_THROW_ERROR("Object Not Found")
catch (...) {
throw ("Object Not Found");
}
; // This is the semicolon that follows DC_THROW_ERROR("Object Not Found")
}
It is that extraneous semicolon, not the macro, that is getting the compiler in a tizzy about control reaching the end of a non-void function. That said, since statements in C and C++ are supposed to end with a semicolon, it is only natural that the human author of the code will add a semicolon after the end of the macro invocation.
Do you really need a macro here? Macros are evil in general. This macro is evil incarnate.
It makes that try-catch block look like invalid syntax. Macros that make the code look invalid are doubly evil.
It renames syntax. Doing #define BEGIN { is evil. Macros that rename syntax are doubly evil.
It invites the programmer to add that semicolon at the end. Macros that should not be followed with a semicolon are doubly evil.
That the macro invocation should not be followed with a semicolon apparently is not documented. Macros that do something evil but don't document the evilness are doubly evil.
All told, this macro is 2x2x2x2, or sixteen-fold evil. That makes this devil code.

Related

Raise compile error if braces not closed at end of file (C++)

Is there a way to raise a warning or error if the C++ compiler comes to the end of file without all braces being closed? We never use headers which spill a scope into another file and would like to receive compiler warnings if it happens by accident. Compiler MSVC 2010, but others might be of interest too.
// Utilities.hpp
namespace example
{
class Utilities
{
}
//<EOF> -> should warn or error
Edit: I am willing to put a marker/pragma/Macro at the end of each file, where I know the brace level should be 0.
A reasonable method is
#define AT_GLOBAL_SCOPE namespace { }
because that can only appear at global or namespace scope. So it unfortunately won't catch that missing } from another namespace, but it will catch the class-case, as well as missing parentheses and semicolons.
In principle, this isn't known by the compiler proper - the preprocessor is sufficiently separate from the compiler proper that different files are "not known", it's just one long stream of source-code as far as the compiler is concerned.
One of the problems here is that the "understanding of the source code" is different at different levels. The preprocessor which inserts the #include ... into the source stream doesn't really know anything about { and } in other ways than "they are not alphanumeric" [which affects how macros and such are handled]. And consider that you could have [even if it's perhaps a bad idea]:
#define START {
#define END }
start
...
...
end
(The C preprocessor CAN be used for other things than C-code, so it's not "meant" to understand the language it is compiling)
I guess you could write a small tool that parses code and just counts up for { and down for }, and check for equality [you have to care for quotes and comments, but everything else should be counted]. But of course, the compiler will eventually tell you in some way, so I'm not sure that's much use. That assumes that there are no uneven sets of braces in macros.

Asserts and unused variables in Visual Studio 2010 SP1

I use the code below for assert in "release", have for some time with no issues ever.
Then along came Visual Studio 2010 Pro SP1, and things went south, as also happened to mr. Krunthar.
Problem is, when I have a piece of code in which I do sanity checks like this:
#define ASSERT(condition, msg) do { (void)sizeof(condition); } while (0,0)
// Note: (0,0) is to avoid warning C4127: conditional expression is constant
{
int result = CallMeOnce(); // its side effects are the important stuff
// perform additional sanity checks in debug
ASSERT(result >= 0, "too low");
ASSERT(result <= 100, "too high");
ASSERT(!isPrime(result), "too prime");
}
VS2010 spits out a warning C4189: 'result' : local variable is initialized but not referenced
I am at a loss on how to fix that:
Code like (void)(condition) will execute any expression passed as condition, which is a no no
Putting CallMeOnce() inside the ASSERT expression is impossible
Refactoring all the different CallMeOnce()s is NOT an option
I'd rather not have to write scaffolding code like (void)result, if (result == result) {} or UNREFERENCED_PARAMETER(result) (or equivalent) outside the macro just to avoid the warning as it makes the code even harder to read (pollution), and is easy to forget while writing code in Debug. Also: in lots of places!
I'm considering creating another macro (ASSERTU?) just for variables, but it feels so... quirky!
Has anyone found a better way out?
Thanks a lot!
Edit: Clarified preference for the variable handling at caller's level
in your assert macro you have
(void)sizeof(condition);
presumably this code was written by someone else, so, explanation:
the rôle of the (void) cast is to tell the compiler that you really intended this do-nothing expression statement to do nothing.
now do the same for your result
that was easy, wasn't it? sometimes solution is just staring you in the face. ;-)
by the way, when this construct is used to suppress warnings about unused formal arguments, you might want to add a redefinition of the name, like
(void) unusedArg; struct unusedArg;
this prevents inadvertently using the argument with later maintenance of the code
however, the error generated by visual c++ is not exactly informative
there are umpteen level of sophistication that can be added, but i think even the name redefinition is perhaps going too far – the cost greater than the advantage, perhaps
You can use the UNREFERENCED_PARAMETER macro.
It seems I got somewhere!
#define ASSERT(condition, msg) \
do { \
if (0,0) { \
(void)(condition); \
} \
} while (0,0)
Mandatory explanation:
(void)(condition); will suppress C4189, but will execute any expression or function call passed in.
However, if (false) {...} will make sure that whatever (valid expression) "..." may be, it will not be executed. Code optimization phase will see it as dead code and throw it away (no code generated at all for the block in my tests!).
Finally, the owl trick (0,0) will prevent C4127, which seems a quite useless warning in the first place but hey, less clutter in the compilation output!
The only weakness I could find to this solution is that condition needs to be compilable code, so if you #ifdef-ed out part of the expression, it will raise an error. It might be that it's also compiling (though not calling) the code for the called functions; more research would be useful.
This is much nicer. Also: an expression instead of a statement
#define ASSERT(condition, msg) ( false ? (void)(condition) : (void)0 )
though you might want both debug and release versions of your assert to have the same semantic, so a do {...} while (0,0) around it might be appropriate.
You can use pairs of __pragma(warning(push)) __pragma(warning(disable: 4127)) and __pragma(warning(pop)) to silence C4127 just for the ASSERT line.
Then (void)(true ? (void)0 : ((void)(expression))) silences C4189.
This is an excerpt from my own implementation of an assertion macro.
The PPK_ASSERT(expression) macro will ultimately expand to PPK_ASSERT_3(level, expression) or PPK_ASSERT_UNUSED(expression) depending on whether assertions are enabled or disabled.
#define PPK_ASSERT_3(level, expression, ...)\
__pragma(warning(push))\
__pragma(warning(disable: 4127))\
do\
{\
static bool _ignore = false;\
if (PPK_ASSERT_LIKELY(expression) || _ignore || pempek::assert::implementation::ignoreAllAsserts());\
else\
{\
if (pempek::assert::implementation::handleAssert(PPK_ASSERT_FILE, PPK_ASSERT_LINE, PPK_ASSERT_FUNCTION, #expression, level, _ignore, __VA_ARGS__) == pempek::assert::implementation::AssertAction::Break)\
PPK_ASSERT_DEBUG_BREAK();\
}\
}\
while (false)\
__pragma(warning(pop))
and
#define PPK_ASSERT_UNUSED(expression) (void)(true ? (void)0 : ((void)(expression)))

Get return type of function in macro (C++)

I have ASSERT(x) macro and I want to call return if it asserts (in release configuration).
To do this I need to know return type of function where I use this ASSERT. How to get it (I deal with C++03, LLVM GCC 4.2 compiler)?
My ASSERT macro:
#define ASSERT(x) \
if(!(x)) {
LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
return /*return_type()*/; \
}
PS: I tried return 0; - compiler shows error for void functions (and I didn't try it for complex returning types), if return; - error for non-void functions.
(Updated...)
I'll answer to werewindle, nyarlathotep and jdv-Jan de Vaan here. I use standard assert for debug configuration. But after beta-testing I still get crash reports from final customers, and in most cases I need to change my crashing functions:
ASSERT (_some_condition_);
if (!_some_condition_) // add this return
return _default_value_;
I understand, that my program may crash probably later (otherwise it will definitely crash in current function). Also I can't quit application because developing is for iPhone (apps may not quit programmatically there). So the easiest way would be to "auto return" when assertion failed.
You can't determine the return type of the surrounding function in a Macro; macros are expanded by the preprocessor, which doesn't have this kind of information about the surroundings where these macros occur; it is basically just "searching and replacing" the macros. You would have to write separate macros for each return type.
But why not exit the program (i.e. calling the exit function)? Just returning from a function doesn't seem like a very robust error handling. Failed assertions should after all only occur when something is terribly wrong (meaning the program is in a state it was not designed to handle), so it is best to quit the program as soon as possible.
There are no proper way to determine return type inside a function in C.
Also, if you somehow implement your variant of ASSERT it will lead to erroneous program behavior. Main idea of ASSERT: if it fails, then program is in undefined state and only proper way is to stop it now. I.e. by calling exit().
i think you can do this with a template function, that you call default(x) from within the macro.
template<class T> default<T>(T x) { return T(); }
that will work for everyting with a default constructor. I think you need to write a special macro for void.
I hope i got the template syntax right, my c++ is getting rusty.
You can't do that, the C/C++ preprocessor is pretty basic and it can't do any code analysis. At most what you can do is pass the return type to the macro.
But here's my opinion: you're using assertions the wrong way. They should only be used for sanity checks of the code (for errors than can only happen because of the programmer); if all assertions pass, you don't need to care about them, you don't need to log them.
And not only that, but (in general) you should employ the element of least surprise. Do you expect ASSERT to log something and then forcefully make the function return? I know I wouldn't. I either expect it to close the application completely (what the standard assert does) or let me decide what happens next (maybe I have some pointers to free).
Macros do not return values, as they are no functions per se. They substitute the source code where they are used, so you'd return in the function where the macro is used.
There is no way to get the return value from a macro.
You could just define another macro for your needs.
#define ASSERT(x) \
if(!(x)) { \
LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
ASSERT_DEFAULT_RETURN(); \
}
And then inside a function:
int foo(){
#ifdef ASSERT_DEFAULT_RETURN
#undef ASSERT_DEFAULT_RETURN
#endif
#define ASSERT_DEFAULT_RETURN() return 0
// ...
ASSERT(some_expression);
// ...
// cleanup
#undef ASSERT_DEFAULT_RETURN
}
Just do this
#define ASSERT(x, ret, type) \
if(!(x)){
LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
return (type) ret;
}
I believe you are trying to solve the wrong problem. You don't want your program to crash in case of assertions, you best improve your testing.
Having a 'return' in these assertions give you a false sense of security. Instead it hides your problems and causes unexpected behavior in your program so the bugs you do get are much more complex. A colleague of mine actually wrote a good blog post about it.
If you really would want it, you could try writing return {}; so it default constructs the value, or have an assert macro where you also provide the failure case. However I really don't recommend it!

Warning message purpose?

While compiling a while loop without a body, I saw this message:
warning: suggest a space before ';' or explicit braces around empty body in
'while' statement
Why should I put a space? Is it to make it clearer that my loop isn't really doing anything?
Yes -- the usual convention is to put it on a line by itself, something like this:
while (*d++ = *s++)
;
A few people prefer to use things like:
while (*d++ = *s++)
{
/* intentionally empty */
}
Why should I put a space? Is it to make it clearer that my loop isn't really doing anything?
Yes, exactly that.
Many inexperienced programmers often put the ; after a control flow statement like for or while because they assume that ; goes at the end of every line, and not just at the end of statements and declarations. The warning is just suggesting to make it clearer that you understand that you've created an empty loop.
A more obvious empty-body loop syntax is to use the continue statement:
while (condition_with_side_effects)
continue;
That way no one will think you've accidentally added an extraneous ;:
while (condition); // bad style
Yes, it is just to show that you have not automatically placed a semicolon at the end of the line by mistake.

do {...} while(false)

I was looking at some code by an individual and noticed he seems to have a pattern in his functions:
<return-type> function(<params>)
{
<initialization>
do
{
<main code for function>
}
while(false);
<tidy-up & return>
}
It's not bad, more peculiar (the actual code is fairly neat and unsurprising). It's not something I've seen before and I wondered if anyone can think of any logic behind it - background in a different language perhaps?
You can break out of do{...}while(false).
A lot of people point out that it's often used with break as an awkward way of writing "goto". That's probably true if it's written directly in the function.
In a macro, OTOH, do { something; } while (false) is a convenient way to FORCE a semicolon after the macro invocation, absolutely no other token is allowed to follow.
And another possibility is that there either once was a loop there or iteration is anticipated to be added in the future (e.g. in test-driven development, iteration wasn't needed to pass the tests, but logically it would make sense to loop there if the function needed to be somewhat more general than currently required)
The break as goto is probably the answer, but I will put forward one other idea.
Maybe he wanted to have a locally defined variables and used this construct to get a new scope.
Remember while recent C++ allows for {...} anywhere, this was not always the case.
I've seen it used as a useful pattern when there are many potential exit points for the function, but the same cleanup code is always required regardless of how the function exits.
It can make a tiresome if/else-if tree a lot easier to read, by just having to break whenever an exit point is reached, with the rest of the logic inline afterwards.
This pattern is also useful in languages that don't have a goto statement. Perhaps that's where the original programmer learnt the pattern.
I've seen code like that so you can use break as a goto of sorts.
I think it's more convenient to write break instead of goto end. You don't even have to think up a name for the label which makes the intention clearer: You don't want to jump to a label with a specific name. You want to get out of here.
Also chances are you would need the braces anyway. So this is the do{...}while(false); version:
do {
// code
if (condition) break; // or continue
// more code
} while(false);
And this is the way you would have to express it if you wanted to use goto:
{
// code
if (condition) goto end;
// more code
}
end:
I think the meaning of the first version is much easier to grasp. Also it's easier to write, easier to extend, easier to translate to a language that doesn't support goto, etc.
The most frequently mentioned concern about the use of break is that it's a badly disguised goto. But actually break has more resemblance to return: Both instructions jump out of a block of code which is pretty much structured in comparison to goto. Nevertheless both instructions allow multiple exit points in a block of code which can be confusing sometimes. After all I would try to go for the most clear solution, whatever that is in the specific situation.
This is just a perversion of while to get the sematics of goto tidy-up without using the word goto.
It's bad form because when you use other loops inside the outer while the breaks become ambiguous to the reader. "Is this supposed to goto exit? or is this intended only to break out of the inner loop?"
This trick is used by programmers that are too shy to use an explicit goto in their code. The author of the above code wanted to have the ability to jump directly to the "cleanup and return" point from the middle of the code. But they didn't want to use a label and explicit goto. Instead, they can use a break inside the body of the above "fake" cycle to achieve the same effect.
Several explanations. The first one is general, the second one is specific to C preprocessor macros with parameters:
Flow control
I've seen this used in plain C code. Basically, it's a safer version of goto, as you can break out of it and all memory gets cleaned up properly.
Why would something goto-like be good? Well, if you have code where pretty much every line can return an error, but you need to react to all of them the same way (e.g. by handing the error to your caller after cleaning up), it's usually more readable to avoid an if( error ) { /* cleanup and error string generation and return here */ } as it avoids duplication of clean-up code.
However, in C++ you have exceptions + RAII for exactly this purpose, so I would consider it bad coding style.
Semicolon checking
If you forget the semicolon after a function-like macro invocation, arguments might contract in an undesired way and compile into valid syntax. Imagine the macro
#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");
That is accidentally called as
if( foo )
PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
doSomethingElse();
The "else" will be considered to be associated with the gDebugModeOn, so when foo is false, the exact reverse of what was intended will happen.
Providing a scope for temporary variables.
Since the do/while has curly braces, temporary variables have a clearly defined scope they can't escape.
Avoiding "possibly unwanted semicolon" warnings
Some macros are only activated in debug builds. You define them like:
#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n)
#endif
Now if you use this in a release build inside a conditional, it compiles to
if( foo )
;
Many compilers see this as the same as
if( foo );
Which is often written accidentally. So you get a warning. The do{}while(false) hides this from the compiler, and is accepted by it as an indication that you really want to do nothing here.
Avoiding capturing of lines by conditionals
Macro from previous example:
if( foo )
DBG_PRINT_NUM(42)
doSomething();
Now, in a debug build, since we also habitually included the semicolon, this compiles just fine. However, in the release build this suddenly turns into:
if( foo )
doSomething();
Or more clearly formatted
if( foo )
doSomething();
Which is not at all what was intended. Adding a do{ ... }while(false) around the macro turns the missing semicolon into a compile error.
What's that mean for the OP?
In general, you want to use exceptions in C++ for error handling, and templates instead of macros. However, in the very rare case where you still need macros (e.g. when generating class names using token pasting) or are restricted to plain C, this is a useful pattern.
It looks like a C programmer. In C++, automatic variables have destructors which you use to clean up, so there should not be anything needed tidying up before the return. In C, you didn't have this RAII idiom, so if you have common clean up code, you either goto it, or use a once-through loop as above.
Its main disadvantage compared with the C++ idiom is that it will not tidy up if an exception is thrown in the body. C didn't have exceptions, so this wasn't a problem, but it does make it a bad habit in C++.
It is a very common practice. In C. I try to think of it as if you want to lie to yourself in a way "I'm not using a goto". Thinking about it, there would be nothing wrong with a goto used similarly. In fact it would also reduce indentation level.
That said, though, I noticed, very often this do..while loops tend to grow. And then they get ifs and elses inside, rendering the code actually not very readable, let alone testable.
Those do..while are normally intended to do a clean-up. By all means possible I would prefer to use RAII and return early from a short function. On the other hand, C doesn't provide you as much conveniences as C++ does, making a do..while one of the best approaches to do a cleanup.
Maybe it’s used so that break can be used inside to abort the execution of further code at any point:
do {
if (!condition1) break;
some_code;
if (!condition2) break;
some_further_code;
// …
} while(false);
I think this is done to use break or continue statements. Some kind of "goto" code logic.
It's simple: Apparently you can jump out of the fake loop at any time using the break statement. Furthermore, the do block is a separate scope (which could also be achieved with { ... } only).
In such a situation, it might be a better idea to use RAII (objects automatically destructing correctly when the function ends). Another similar construct is the use of goto - yes, I know it's evil, but it can be used to have common cleanup code like so:
<return-type> function(<params>)
{
<initialization>
<main code for function using "goto error;" if something goes wrong>
<tidy-up in success case & return>
error:
<commmon tidy-up actions for error case & return error code or throw exception>
}
(As an aside: The do-while-false construct is used in Lua to come up for the missing continue statement.)
How old was the author?
I ask because I once came across some real-time Fortran code that did that, back in the late 80's. It turns out that is a really good way to simulate threads on an OS that doesn't have them. You just put the entire program (your scheduler) in a loop, and call your "thread" routines" one by one. The thread routines themselves are loops that iterate until one of a number of conditions happen (often one being a certain amount of time has passed). It is "cooperative multitasking", in that it is up to the individual threads to give up the CPU every now and then so the others don't get starved. You can nest the looping subprogram calls to simulate thread priority bands.
Many answerers gave the reason for do{(...)break;}while(false). I would like to complement the picture by yet another real-life example.
In the following code I had to set enumerator operation based on the address pointed to by data pointer. Because a switch-case can be used only on scalar types first I did it inefficiently this way
if (data == &array[o1])
operation = O1;
else if (data == &array[o2])
operation = O2;
else if (data == &array[on])
operation = ON;
Log("operation:",operation);
But since Log() and the rest of code repeats for any chosen value of operation I was wandering how to skip the rest of comparisons when the address has been already discovered. And this is where do{(...)break;}while(false) comes in handy.
do {
if (data == &array[o1]) {
operation = O1;
break;
}
if (data == &array[o2]) {
operation = O2;
break;
}
if (data == &array[on]) {
operation = ON;
break;
}
} while (false);
Log("operation:",operation);
One may wonder why he couldn't do the same with break in an if statement, like:
if (data == &array[o1])
{
operation = O1;
break;
}
else if (...)
break interacts solely with the closest enclosing loop or switch, whether it be a for, while or do .. while type, so unfortunately that won't work.
In addition to the already mentioned 'goto examples', the do ... while (0) idiom is sometimes used in a macro definition to provide for brackets in the definition and still have the compiler work with adding a semi colon to the end of a macro call.
http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q=while+(0)
I agree with most posters about the usage as a thinly disguised goto. Macros have also been mentioned as a potential motivation for writing code in the style.
I have also seen this construct used in mixed C/C++ environments as a poor man's exception. The "do {} while(false)" with a "break" can be used to skip to the end of the code block should something that would normally warrant an exception be encountered in the loop.
I have also sen this construct used in shops where the "single return per function" ideology is enforced. Again, this is in lieu of an explicit "goto" - but the motivation is to avoid multiple return points, not to "skip over" code and continue actual execution within that function.
I work with Adobe InDesign SDK, and the InDesign SDK examples have almost every function written like this. It is due to fact that the function are usually really long. Where you need to do QueryInterface(...) to get anything from the application object model. So usually every QueryInterface is followed by if not went well, break.
Many have already stated the similarity between this construct and a goto, and expressed a preference for the goto. Perhaps this person's background included an environment where goto's were strictly forbidden by coding guidelines?
The other reason I can think of is that it decorates the braces, whereas I believe in a newer C++ standard naked braces are not okay (ISO C doesn't like them). Otherwise to quiet a static analyzer like lint.
Not sure why you'd want them, maybe variable scope, or advantage with a debugger.
See Trivial Do While loop, and Braces are Good from C2.
To clarify my terminology (which I believe follows standard usage):
Naked braces:
init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();
Empty braces (NOP):
{}
e.g.
while (1)
{} /* Do nothing, endless loop */
Block:
if (finished)
{
closewindows(&windows);
freememory(&cache);
}
which would become
if (finished)
closewindows(&windows);
freememory(&cache);
if the braces are removed, thus altering the flow of execution, not just the scope of local variables. Thus not 'freestanding' or 'naked'.
Naked braces or a block may be used to signify any section of code that might be a potential for an (inline) function that you wish to mark, but not refactor at that time.
It's a contrived way to emulate a GOTO as these two are practically identical:
// NOTE: This is discouraged!
do {
if (someCondition) break;
// some code be here
} while (false);
// more code be here
and:
// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here
On the other hand, both of these should really be done with ifs:
if (!someCondition) {
// some code be here
}
// more code be here
Although the nesting can get a bit ugly if you just turn a long string of forward-GOTOs into nested ifs. The real answer is proper refactoring, though, not imitating archaic language constructs.
If you were desperately trying to transliterate an algorithm with GOTOs in it, you could probably do it with this idiom. It's certainly non-standard and a good indicator that you're not adhering closely to the expected idioms of the language, though.
I'm not aware of any C-like language where do/while is an idiomatic solution for anything, actually.
You could probably refactor the whole mess into something more sensible to make it more idiomatic and much more readable.
Some coders prefer to only have a single exit/return from their functions. The use of a dummy do { .... } while(false); allows you to "break out" of the dummy loop once you've finished and still have a single return.
I'm a java coder, so my example would be something like
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class p45
{
static List<String> cakeNames = Arrays.asList("schwarzwald torte", "princess", "icecream");
static Set<Integer> forbidden = Stream.of(0, 2).collect(Collectors.toSet());
public static void main(String[] argv)
{
for (int i = 0; i < 4; i++)
{
System.out.println(String.format("cake(%d)=\"%s\"", i, describeCake(i)));
}
}
static String describeCake(int typeOfCake)
{
String result = "unknown";
do {
// ensure type of cake is valid
if (typeOfCake < 0 || typeOfCake >= cakeNames.size()) break;
if (forbidden.contains(typeOfCake)) {
result = "not for you!!";
break;
}
result = cakeNames.get(typeOfCake);
} while (false);
return result;
}
}
In such cases I use
switch(true) {
case condution1:
...
break;
case condution2:
...
break;
}
This is amusing. There are probably breaks inside the loop as others have said. I would have done it this way :
while(true)
{
<main code for function>
break; // at the end.
}