Question

Let's say I have a function:

int AndTwoNum(int N, int M, int i)
{
    if ((i < 0) || (i > 31))
    {
        return  //what should I return here?
    }

    int mask = ~0 << i;
    int N_modify = N & mask;
    int M_modify = M & (~mask);

    return N_modify | M_modify;
}

This function replace the 0 to i bits of N with the 0 to i bits of M and return the value. However here we have to check whether i is within range [0, 31]. If it is not, we need to stop the function right away. However, I don't know what to return here for an unexpected i.

Was it helpful?

Solution

An option could be to just throw an exception in case of invalid input, e.g.

#include <stdexcept>   // For std::invalid_argument
...

int AndTwoNum(int N, int M, int i)
{
    // Check 'i' range.
    if ((i < 0) || (i > 31))
    {
        throw std::invalid_argument("'i' is out of valid range (0-31).");
    }
    ...

OTHER TIPS

If you want to return an integer on an error: there is no hardcoded rule for what to return on an error. Some functions return (-1) as this is expressive, but other return (0). Important thing is this value must be out of the domain of possible results, otherwise how would you know this is actually an error? In your case (-1) sounds reasonable as this is out of the domain of possible results.

int AndTwoNum(int N, int M, int i)
{
    if ((i < 0) || (i > 31))
    {
        return  (-1);
    }
    //...

In C++ you can also throw an exception.

#include <stdexcept>

int AndTwoNum(int N, int M, int i)
{
    if ((i < 0) || (i > 31))
    {
      throw std::invalid_argument("argument out of domain");
    }
    //...

Be sure to describe the bahavior to the the user giving correct description.

I prefer using std::optional for cases like this:

#include <optional>

std::optional<int> AndTwoNum(int N, int M, int i)
{
    if ((i < 0) || (i > 31))
    {
        return  std::optional<int>(); // I got nothing for ya
    }

    int mask = ~0 << i;
    int N_modify = N & mask;
    int M_modify = M & (~mask);

    return std::optional<int>(N_modify | M_modify);
}

Then to use it:

auto n = AndTwoNum(...);
if (n) { // we got a value
    int i = *n; // unpack the value
} else {
    // no value
}

The bad news is, std::optional is not part of the current (C++11) standard. As far as I know, it's slated to be part of C++14. So compiler support is spotty. You can also use Boost.Optional in the interim, which is what std::optional is based on.

Another alternative is to return a std::pair<int, bool> where the bool portion is used to indicate whether or not the int has a valid value. This is, essentially, what std::optional does, but with a cleaner interface.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top