Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::errc, how to indicate success in retval

Tags:

c++

c++14

I would like to write a c++ function like this:

#include <system_error>
std::errc f() { return std::errc::success; }

But I can't understand how to return a successful value (0 in this case) using std::errc 'enum class' type. The one way i see is to return int:

template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) {
    return static_cast<typename std::underlying_type<E>::type>(e);
}

int f() { is_succ() ? 0 : to_underlying(err); }

But it looks ugly for me. Is where a standard way to return a C-oriented success/error code from a function in a std c++ 0x14?

PS. I'm using MS VC 2015 Patch 2.

like image 533
user2073942 Avatar asked Apr 24 '16 15:04

user2073942


2 Answers

You can do it like this:

#include <system_error>

std::errc f() { return std::errc(); }

int main()
{
    std::errc x = f();
    if (x == std::errc())
    {
        // success
    }
}

std::errc() (0) is a valid enumeration value even though it does not appear in the enumerator list, which start at 1. It represents success.

For comparison, have a look at std::to_chars, which returns a

struct to_chars_result {
    char* ptr;
    std::errc ec;
}
like image 105
Daniel Avatar answered Oct 22 '22 18:10

Daniel


You generally don't return a std::errc value from a function directly. Instead, you return a std::error_code. For example, your function would be declared like this:

std::error_code f();

You then compare the result of that function against the std::errc values. For example:

std::error_code error = f();
if (error == std::errc::no_such_file_or_directory)
{
  // deal with the error
}

std::error_codeis contextually convertible bool. The way you test if a function succeeded is by using the error code in a boolean expression. For example:

std::error_code error = f();
if (error)
{
  // the function failed...
}

To return success from such a function, you return a default initialized std::error_code. For example:

std::error_code f()
{
  // do stuff...
  return std::error_code{}; // success!
}

This approach works well when you're consuming a C-style API. Your wrapper would construct std::error_code objects using the integer values returned by the API and a custom std::error_category that defines how to translate those errors into std::errc values.

The opposite doesn't work, however. If you're writing a C wrapper for a C++ library, then you have to do things the C way. Define an enum with your error values and return those values from your C entry points.

like image 6
Peter Ruderman Avatar answered Oct 22 '22 18:10

Peter Ruderman