tags:

views:

400

answers:

13

Given a function that returns a value, is it possible to exit the function given a certain condition without returning anything? If so, how can you accomplish this?

Example:

int getNumber ()
{ 
    . . . 
}

So say you are in this function. Is there a way to exit it without it doing anything?

A: 

In C++ a function must return a value (value type, reference, or address) if one is specified in the function declaration/definition.

xgalaxy
+1  A: 

You could throw a specified exception and catch it accordingly.

Simon Linder
A: 

You could throw an exception. You'd not return anything, but you'll have to catch the exception to determine what to do next (you could always swallow the exception and do nothing to achieve what you want).

Jeff Foster
+11  A: 

You have two options: return something or throw.

int getNumber() 
{
    return 3;
}

int getNumber() 
{
    throw string("Some Var");
}

If you throw, you have to catch the type you threw.

int maint(int argc, char ** argc)
{
     try
     {
           getNumber();
     }
     catch(string std)
     {
          //Your code will execute here if you throw
     }
 }
rerun
Only use the throw alternative if returning no value is an error. Its hard to analyze code that uses throwing exceptions for normal code flow.
Totonga
yes Great point this is a no no as a standard practice.
rerun
And, by the way, exceptions are quite expensive in C++: both the try block and the throw are costly, and should be used only for errors (i.e., in really *exceptional* scenarios).
Matteo Italia
Not really true on the "expensive" part (depending on the runtime), but yes, exceptions are for *exceptional* (and erroneous) conditions, not as an alternative control flow.
DevSolar
@DevSolar: They're not expensive in terms of running time in the non-exceptional case, but they are expensive in terms of code size.
Billy ONeal
A: 

A redesign of your method is likely in order if you need to break out of a function that's meant to return a value...or you could simply return an "error" value of some sort.

Xorlev
+15  A: 

You might get away with a return; with no return value. The compiler will warn, but may not error.

BUT, why on earth would you even consider this? What are you trying to achieve?

And what does the calling code look like? If it is int someVar = getNumber(); then the value of someVar is undefined (which is A Bad Thing).

It sounds to me like you want to return two pieces of information, one of which tells you if the other is valid.

Try something like

bool GetNumber(int * outputNumber)
{
   if ....
   {
      *outputNumber = ...;
      return true;
   }  
   else
   {
      return false; // contents of outputNumber are undefined
   }
}

int number;
bool isNumberValid;
isNumberValid = GetNumber(&number);
if (isNumberValid)
    ... do something with number
Mawg
The standard never requires an error, merely a "diagnostic". Hence it treats warnings and ewrors equally. But don't let that fool you: omitting a return value _is_ an error.
MSalters
+1 in my book, **all** warnings are errors. I don't tolerate them. And this would be really egregious.
Mawg
A: 

What is your actual use case?

If you really need to not return anything and terminate the normal function execution, you can throw an exception.

You can also return something that the caller interprets as an error (or 'nothing returned').

Whatever your solution is, the caller needs to handle the 'nothing returned' case separately, e.g. catch the exception or check the returned value.

Anssi
+2  A: 
zabulus
A: 

You could use setjmp/longjmp (see http://en.wikipedia.org/wiki/Setjmp.h), but from a software engineering perspective you are better off using either exceptions or error codes as mentioned by others here.

Remy
+3  A: 

For float and double there is an alternative but not for int types.

#include <limits>

double Get()
{
  // no valid return value
  return std::numeric_limits<double>::quiet_NaN();
}

double val = Get();
if(val != val) {
  // Retrieved no valid return value 
}
else {
  // No NaN retrieved
}

Be careful when using NaN. Each condition on val will be true.

Totonga
I don't agree, NaN is a float like any other (in this context). The value of whatever he's returning may already be NaN. I'd always rather add an additional bool out parameter, than add an assumption to the contract between the caller and callee.
Nikola Gedelovski
Totonga
+1  A: 

You could also return a class/struct with some magic conversion that is useful for your special need.

Real-life example: once I had actually to return two pieces of information in the same return value, a value to report if a window message had been completely processed and the value to be returned for it if the processing was already completed. So I packed everything up in a class like this:

//This class is used to carry a return value for a window message and a value that indicates if the
//message has already been completely processed
class MessageReturnValue
{
public:
    LRESULT returnValue;
    bool processed;
    MessageReturnValue()
    {
        processed=false;
        returnValue=FALSE;
    };
    MessageReturnValue(LRESULT ReturnValue)
    {
        processed=true;
        returnValue=ReturnValue;
    };
    MessageReturnValue(bool Processed)
    {
        returnValue=FALSE;
        processed=Processed;
    };
    inline operator bool()
    {
        return processed;
    };
    inline operator LRESULT()
    {
        return returnValue;
    };
};

This allowed me to do just return false; in a function that returned a MessageReturnValue if the message had still to be processed, or to return TRUE/15/whatever; if the message had been completely processed and I already had a return value. The caller, on its side, could simply do

LRESULT MyWndProc(/* blah blah blah */)
{
    MessageReturnValue ret = MyFunction(/* blah blah blah */);
    if(!ret)
    {
        /* process the message */
        return /* something */;
    }
    else
        return (LRESULT)ret;
}

If you have more complicated needs, you could also consider using boost::tuple.

Matteo Italia
+8  A: 

Simple solution:

boost::optional<int> getNumber( )
{
  // May now return an int, or may return nothing.
}
MSalters
You have to return something, even if it's just an "empty" optional<int> object. Not returning anything causes undefined behaviour for all functions other than main and those that return void.
sellibitze
Is it undefined behavior or a default constructed object (undefined for built-ins / pods) ? Anyway +1 for suggesting `boost::optional`, that's the way with optional values...
Matthieu M.
@sellibitze: of course for this code "nothing" means `boost::optional<int>()`. See the attached comment: "implement a get function for a queue that will do [return] nothing if the queue is empty ".
MSalters
It's incredible: whichever utility class you may think about, it's already there in boost and it's better than any class of that kind that you could have wrote (it's more generic/tidy/RAII/interacts better with the std lib and boost/...).
Matteo Italia
Bonus: the docs of boost::optional already discuss the various approaches to this problem that we are talking about here. So boost not only provides ready-to-use code, but also preempts discussions in forums. A bit creepy, if you think about it.
Matteo Italia
+3  A: 

Make it a requirement for the user to check first that the queue is not empty (provide means for that).

Then you can:

  • not check anything and simply invoke undefined behavior (access underlying data as if it was there) - it's the user's fault
  • check and throw exception
  • assert (result is undefined with NDEBUG)

Checking and then invoking undefined behavior (returning an arbitrary value) is the worst thing to do. You get both the runtime overhead of the check and the caller is no wiser, as the result is still undefined.

visitor
+1, IMO best solution in this use case
sellibitze
This is a bit problematic in multi-threaded environments, especially if multiple threads are reading.
MSalters