How to say that there is no result of a function with a return value?

I have a short question. Given a function that returns a class object as a result, what should I return if there is no result (say, because the index is out of range)? I could return a new “empty” object, but how can I indicate that there were no successful calculations?

I assume there is a general approach.

+5
source share
6 answers

You can throw an exception if the values ​​do not match the expected results.

The tutorial can be found at http://www.cplusplus.com/doc/tutorial/exceptions

The exception works with the principle of try and catch.

"" . - , "" , - , . , , .

.

+2

++ , , , boost::optional.

, - , boost::optional -approach , , . , , - SQL NULL. boost::optional .

+13

vector:: at throw out_of_range , .

+3

, .

, :

#include <stdexcept> // Necessary for standard exceptions

X foo()
{
    ...
    if (/* something goes wrong... */)
    {
        // There may be a more appropriate exception class. You could
        // also derive your own exception class from std::exception...
        throw std::logic_error("Whatever!"); 
    }

    ...
}

...

try
{
    X x = foo();
    // Work with x...
}
catch (std::logic_error const& e) // Catch what is appropriate...
{
    std::cout << e.what();
}

no , Boost.Optional. , "" X, , bool, , , :

std::pair<X, bool> foo();

...

bool valid;
X x;
std::tie(x, valid) = foo();
if (valid)
{
    // Use x...
}
+3

, - .

#include<exception>

Object * GenerateObject(int i)
{
    if (i < 0)
        throw std::out_of_range("i");

    return new Object(i);
}

int main(int argc, char * argv[])
{
     try
     {
         Object * obj = GenerateObject(-1);

         // Succeeded
         return 0;
     }
     catch (std::exception & e)
     {
         // Failed, exiting with error value
         return 1;
     } 
}

, , .

class Rectangle
{
private:
    int left, top, width, height;

public:
    Rectangle(l, t, w, h)
    {
        left = l;
        top = t;
        width = w;
        height = h;
    }

    public static Rectangle empty;
}

Rectangle Rectangle::empty = Rectangle(0, 0, -1, -1);

// ...

Rectangle DoSth(int i)
{
     // i < 0 is NOT considered an error here
     if (i < 0)
          return Rectangle::empty;

     // Further processing
}
+3

You can associate an enumeration with the return type of an object. If the return enumeration is a specific value, the object is valid, otherwise the object is in an invalid state.

// This is a working C++11 example.
#include <utility>
#include <memory>

enum result
{
    ok,
    out_of_range,
    some_other_error
};

class object
{
    public:
        object() {}
};

typedef std::shared_ptr< object > object_ptr;

typedef std::pair< result, object_ptr > return_type;

return_type some_function( int index )
{
    if ( index > 5 )
    {
        return return_type{ result::out_of_range, nullptr };
    }

    return return_type{ result::ok, object_ptr{ new object() } };
}

int main()
{
    return_type res = some_function( 10 );
    if ( res.first == result::ok )
    {
        // Do something with res.second
    }
    else
    {
        // Handle the error
    }
}

I would just throw an exception.

0
source

All Articles