Introduction
Error conditions originating from the operating system or other low-level
application program interfaces (API’s) are typically reported via an integer
representing an error code. When these low-level API calls are wrapped in
portable code, such as in a portable library, some users want to deal with the
error codes in portable ways. Other users need to get at the system specific
error codes, so they can deal with system specific needs. The Boost System
library provides simple, light-weight error_code objects that encapsulate
system-specific error code values, yet also provide access to more abstract
and portable error conditions via error_condition objects.
Because error_code objects can represent errors from sources other than the
operating system, including user-defined sources, each error_code and
error_condition has an associated error_category.
An exception class, system_error, is provided. Derived from
std::runtime_error, it captures the underlying error_code for the problem
causing the exception so that this important information is not lost.
While exceptions are the preferred C++ default error code reporting mechanism, users of libraries dependent on low-level API’s often need overloads reporting error conditions via error code arguments and/or return values rather than via throwing exceptions. Otherwise, when errors are not exceptional occurrences and must be dealt with as they arise, programs become littered with try/catch blocks, unreadable, and inefficient. The Boost System library supports both error reporting by exception and by error code.
In addition to portable errors codes and conditions supported by the
error_code.hpp header, system-specific headers support the Cygwin, Linux,
and Windows platforms. These headers are effectively no-ops if included for
platforms other than their intended target.
Boost.System is part of the C++11 Standard Library. A number of changes, particularly to names, were made by the C++ committee during standardization. The Boost implementation has been tracking those changes. See Deprecated Names for synonyms provided to prevent breakage of existing user code.
Usage Examples
All of the following examples assume that these lines
#include <boost/system.hpp>
namespace sys = boost::system;
are in effect.
Returning Errors from OS APIs under POSIX
Let’s suppose that we’re implementing a portable file wrapper
over the OS file APIs. Its general outline is shown below:
class file
{
private:
int fd_;
public:
// ...
std::size_t read( void * buffer, std::size_t size, sys::error_code& ec );
std::size_t write( void const * buffer, std::size_t size, sys::error_code& ec );
};
Since we’re implementing the POSIX version of file, its
data member is a POSIX file descriptor int fd_;, although other
implementations will differ.
Our read and write functions return the number of bytes transferred, and signal
errors via the output parameter ec, of type boost::system::error_code.
An implementation of file::read might look like this:
std::size_t file::read( void * buffer, std::size_t size, sys::error_code& ec )
{
ssize_t r = ::read( fd_, buffer, size );
if( r < 0 )
{
ec.assign( errno, sys::system_category() );
return 0;
}
ec = {}; // ec.clear(); under C++03
return r;
}
We first call the POSIX API read; if it returns an error, we store the errno
value in ec, using the system category, and return 0 as bytes transferred.
Otherwise, we clear ec to signal success, and return the result of ::read.
|
Note
|
Clearing ec on successful returns is an important step; do not omit it.
|
Under POSIX, the system category corresponds to POSIX errno values, which is
why we use it.
In principle, since the generic category also corresponds to errno values
under all platforms, we could have used it here; however, by convention under
POSIX, if the errno value comes from the OS (the "system"), we use the system
category for it. That’s because the system category values may be a
platform-specific superset of the generic (platform-independent) values.
The implementation of file::write is basically the same. We show it here for
completeness:
std::size_t file::write( void const * buffer, std::size_t size, sys::error_code& ec )
{
ssize_t r = ::write( fd_, buffer, size );
if( r < 0 )
{
ec.assign( errno, sys::system_category() );
return 0;
}
ec = {}; // ec.clear(); under C++03
return r;
}
Returning Errors from OS APIs under Windows
Under Windows, our file object will store a HANDLE instead of an int:
class file
{
private:
HANDLE fh_;
public:
// as before
};
and the implementation of file::read will look like this:
std::size_t file::read( void * buffer, std::size_t size, sys::error_code& ec )
{
DWORD r = 0;
if( ::ReadFile( fh_, buffer, size, &r, 0 ) )
{
// success
ec = {}; // ec.clear(); under C++03
}
else
{
// failure
ec.assign( ::GetLastError(), sys::system_category() );
}
// In both cases, r is bytes transferred
return r;
}
Here, the system category corresponds to the values defined in the system
header <winerror.h> and returned by GetLastError(). Since we use the
Win32 API ReadFile to implement file::read, and it returns the error
code via GetLastError(), we again store that value in ec as belonging
to the system category.
The implementation of file::write is, again, the same.
std::size_t file::write( void const * buffer, std::size_t size, sys::error_code& ec )
{
DWORD r = 0;
if( ::WriteFile( fh_, buffer, size, &r, 0 ) )
{
ec = {}; // ec.clear(); under C++03
}
else
{
ec.assign( ::GetLastError(), sys::system_category() );
}
return r;
}
Returning Specific Errors under POSIX
Our implementation of file::read has a problem; it accepts std::size_t
values for size, but the behavior of ::read is unspecified when the
requested value does not fit in ssize_t. To avoid reliance on unspecified
behavior, let’s add a check for this condition and return an error:
std::size_t file::read( void * buffer, std::size_t size, sys::error_code& ec )
{
if( size > SSIZE_MAX )
{
ec.assign( EINVAL, sys::generic_category() );
return 0;
}
ssize_t r = ::read( fd_, buffer, size );
if( r < 0 )
{
ec.assign( errno, sys::system_category() );
return 0;
}
ec = {}; // ec.clear(); under C++03
return r;
}
In this case, since we’re returning the fixed errno value EINVAL, which
is part of the portable subset defined by the generic category, we mark the
error value in ec as belonging to the generic category.
It’s possible to use system as well, as EINVAL is also a system category
value under POSIX; however, using the generic category for values belonging
to the portable errno subset is slightly preferrable.
Our implementation of file::write needs to uindergo a similar treatment.
There, however, we’ll apply another change. When there’s no space left on
the disk, ::write returns a number of bytes written that is lower than
what we requested with size, but our function signals no error. We’ll make
it return ENOSPC in this case.
std::size_t file::write( void const * buffer, std::size_t size, sys::error_code& ec )
{
if( size > SSIZE_MAX )
{
ec.assign( EINVAL, sys::generic_category() );
return 0;
}
ssize_t r = ::write( fd_, buffer, size );
if( r < 0 )
{
ec.assign( errno, sys::system_category() );
return 0;
}
if( r < size )
{
ec.assign( ENOSPC, sys::system_category() );
}
else
{
ec = {}; // ec.clear(); under C++03
}
return r;
}
We’ve used the system category to make it appear that the ENOSPC value
has come from the ::write API, mostly to illustrate that this is also a
possible approach. Using a generic value would have worked just as well.
Returning Specific Errors under Windows
Not much to say; the situation under Windows is exactly the same. The only
difference is that we must use the generic category for returning errno
values. The system category does not work; the integer values in the system
category are entirely different from those in the generic category.
std::size_t file::read( void * buffer, std::size_t size, sys::error_code& ec )
{
DWORD r = 0;
if( size > MAXDWORD )
{
ec.assign( EINVAL, sys::generic_category() );
}
else if( ::ReadFile( fh_, buffer, size, &r, 0 ) )
{
ec = {}; // ec.clear(); under C++03
}
else
{
ec.assign( ::GetLastError(), sys::system_category() );
}
return r;
}
std::size_t file::write( void const * buffer, std::size_t size, sys::error_code& ec )
{
DWORD r = 0;
if( size > MAXDWORD )
{
ec.assign( EINVAL, sys::generic_category() );
}
else if( ::WriteFile( fh_, buffer, size, &r, 0 ) )
{
if( r < size )
{
ec.assign( ENOSPC, sys::generic_category() );
}
else
{
ec = {}; // ec.clear(); under C++03
}
}
else
{
ec.assign( ::GetLastError(), sys::system_category() );
}
return r;
}
Attaching a Source Location to Error Codes
Unlike the standard <system_error>, Boost.System allows source locations
(file:line:function) to be stored in error_code, so that functions handling
the error can display or log the source code location where the error occurred.
To take advantage of this functionality, our POSIX file::read function needs
to be augmented as follows:
std::size_t file::read( void * buffer, std::size_t size, sys::error_code& ec )
{
if( size > SSIZE_MAX )
{
static constexpr boost::source_location loc = BOOST_CURRENT_LOCATION;
ec.assign( EINVAL, sys::generic_category(), &loc );
return 0;
}
ssize_t r = ::read( fd_, buffer, size );
if( r < 0 )
{
static constexpr boost::source_location loc = BOOST_CURRENT_LOCATION;
ec.assign( errno, sys::system_category(), &loc );
return 0;
}
ec = {}; // ec.clear(); under C++03
return r;
}
That is, before every ec.assign statement, we need to declare a
static constexpr variable holding the current source location, then pass
a pointer to it to assign. Since error_code is small and there’s no space
in it for more than a pointer, we can’t just store the source_location in it
by value.
BOOST_CURRENT_LOCATION is a macro expanding to the current source location
(a combination of __FILE__, __LINE__, and BOOST_CURRENT_FUNCTION.)
It’s defined and documented in Boost.Assert.
Under C++03, instead of static constexpr, one needs to use static const.
Another option is BOOST_STATIC_CONSTEXPR, a
Boost.Config macro that expands to either
static constexpr or static const, as appropriate.
To avoid repeating this boilerplate each time we do ec.assign, we can define
a macro:
#define ASSIGN(ec, ...) { \
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION; \
(ec).assign(__VA_ARGS__, &loc); }
which we can now use to augment, for example, the POSIX implementation of file::write:
std::size_t file::write( void const * buffer, std::size_t size, sys::error_code& ec )
{
if( size > SSIZE_MAX )
{
ASSIGN( ec, EINVAL, sys::generic_category() );
return 0;
}
ssize_t r = ::write( fd_, buffer, size );
if( r < 0 )
{
ASSIGN( ec, errno, sys::system_category() );
return 0;
}
if( r < size )
{
ASSIGN( ec, ENOSPC, sys::generic_category() );
}
else
{
ec = {}; // ec.clear(); under C++03
}
return r;
}
Obtaining Textual Representations of Error Codes for Logging and Display
Assuming that we have an error_code instance ec, returned to us by some
function, we have a variety of means to obtain textual representations of the
error code represented therein.
ec.to_string() gives us the result of streaming ec into a std::ostream,
e.g. if std::cout << ec << std::endl; outputs system:6, this is what
ec.to_string() will return. (system:6 under Windows is ERROR_INVALID_HANDLE
from <winerror.h>.)
To obtain a human-readable error message corresponding to this code, we can
use ec.message(). For ERROR_INVALID_HANDLE, it would give us "The handle is
invalid" - possibly localized.
If ec contains a source location, we can obtain its textual representation
via ec.location().to_string(). This will give us something like
C:\Projects\testbed2019\testbed2019.cpp:98 in function 'unsigned __int64 __cdecl file::read(void *,unsigned __int64,class boost::system::error_code &)'
if there is a location in ec, and
(unknown source location)
if there isn’t. (ec.has_location() is true when ec contains a location.)
Finally, ec.what() will give us a string that contains all of the above,
something like
The handle is invalid [system:6 at C:\Projects\testbed2019\testbed2019.cpp:98 in function 'unsigned __int64 __cdecl file::read(void *,unsigned __int64,class boost::system::error_code &)']
Most logging and diagnostic output that is not intended for the end user would
probably end up using what(). (ec.what(), augmented with the prefix
supplied at construction, is also what boost::system::system_error::what()
would return.)
Composing Functions Returning Error Codes
Let’s suppose that we need to implement a file copy function, with the following interface:
std::size_t file_copy( file& src, file& dest, sys::error_code& ec );
file_copy uses src.read to read bytes from src, then writes these bytes
to dest using dest.write. This continues until one of these operations signals
an error, or until end of file is reached. It returns the number of bytes written,
and uses ec to signal an error.
Here is one possible implementation:
std::size_t file_copy( file& src, file& dest, sys::error_code& ec )
{
std::size_t r = 0;
for( ;; )
{
unsigned char buffer[ 1024 ];
std::size_t n = src.read( buffer, sizeof( buffer ), ec );
// read failed, leave the error in ec and return
if( ec.failed() ) return r;
// end of file has been reached, exit loop
if( n == 0 ) return r;
r += dest.write( buffer, n, ec );
// write failed, leave the error in ec and return
if( ec.failed() ) return r;
}
}
Note that there is no longer any difference between POSIX and Windows
implementations; their differences are contained in file::read and
file::write. file_copy is portable and works under any platform.
The general pattern in writing such higher-level functions is that
they pass the output error_code parameter ec they received from
the caller directly as the output parameter to the lower-level functions
they are built upon. This way, when they detect a failure in an intermediate
operation (by testing ec.failed()), they can immediately return to the
caller, because the error code is already in its proper place.
Note that file_copy doesn’t even need to clear ec on success, by
using ec = {};. Since we’ve already tested ec.failed(), we know that
ec contains a value that means success.
Providing Dual (Throwing and Nonthrowing) Overloads
Functions that signal errors via an output error_code& ec parameter
require that the caller check ec after calling them, and take appropriate
action (such as return immediately, as above.) Forgetting to check ec
results in logic errors.
While this is a preferred coding style for some, others prefer exceptions, which one cannot forget to check.
An approach that has been introduced by
Boost.Filesystem (which later turned
into std::filesystem) is to provide both alternatives: a nonthrowing
function taking error_code& ec, as file_copy above, and a throwing
function that does not take an error_code output parameter, and throws
exceptions on failure.
This is how this second throwing function is typically implemented:
std::size_t file_copy( file& src, file& dest )
{
sys::error_code ec;
std::size_t r = file_copy( src, dest, ec );
if( ec.failed() ) throw sys::system_error( ec, __func__ );
return r;
}
That is, we simply call the nonthrowing overload of file_copy, and if
it signals failure in ec, throw a system_error exception.
We use our function name __func__ (file_copy) as the prefix, although
that’s a matter of taste.
Note that typically under this style the overloads taking error_code& ec
are decorated with noexcept, so that it’s clear that they don’t throw
exceptions (although we haven’t done so in the preceding examples in order
to keep the code C++03-friendly.)
result<T> as an Alternative to Dual APIs
Instead of providing two functions for every operation, an alternative
approach is to make the function return sys::result<T> instead of T.
result<T> is a class holding either T or error_code, similar to
variant<T, error_code>.
Clients that prefer to check for errors and not rely on exceptions can
test whether a result<T> r contains a value via if( r ) or its more
verbose equivalent if( r.has_value() ), then obtain the value via
*r or r.value(). If r doesn’t contain a value, the error_code
it holds can be obtained with r.error().
Those who prefer exceptions just call r.value() directly, without
checking. In the no-value case, this will automatically throw a
system_error corresponding to the error_code in r.
Assuming our base file API is unchanged, this variation of file_copy
would look like this:
sys::result<std::size_t> file_copy( file& src, file& dest )
{
std::size_t r = 0;
sys::error_code ec;
for( ;; )
{
unsigned char buffer[ 1024 ];
std::size_t n = src.read( buffer, sizeof( buffer ), ec );
if( ec.failed() ) return ec;
if( n == 0 ) return r;
r += dest.write( buffer, n, ec );
if( ec.failed() ) return ec;
}
}
The only difference here is that we return ec on error, instead of
r.
Note, however, that we can no longer return both an error code and a
number of transferred bytes; that is, we can no longer signal partial
success. This is often not an issue at higher levels, but lower-level
primitives such as file::read and file::write might be better off
written using the old style.
Nevertheless, to demonstrate how result returning APIs are composed,
we’ll show how file_copy would look if file::read and file::write
returned result<size_t>:
class file
{
public:
// ...
sys::result<std::size_t> read( void * buffer, std::size_t size );
sys::result<std::size_t> write( void const * buffer, std::size_t size );
};
sys::result<std::size_t> file_copy( file& src, file& dest )
{
std::size_t m = 0;
for( ;; )
{
unsigned char buffer[ 1024 ];
auto r = src.read( buffer, sizeof( buffer ) );
if( !r ) return r;
std::size_t n = *r;
if( n == 0 ) return m;
auto r2 = dest.write( buffer, n );
if( !r2 ) return r2;
std::size_t n2 = *r2;
m += n2;
}
}
Revision History
Changes in Boost 1.78
-
Added support for source locations to
error_code. -
Added
error_code::to_string,error_condition::to_string,error_code::what. -
system_error::what()now contains the source location, if present. -
Added
result<T, E = error_code>, a class holding either a value or an error, defined in<boost/system/result.hpp>.
Changes in Boost 1.77
-
The conversion operator from
error_categorytostd::error_categoryhas been improved and no longer requires<map>or<mutex>. -
The comparison operators of
error_categoryare now inline friends instead of member functions (a side effect of the previous change.) -
error_conditionnow defers callinggeneric_category()to avoid instantiating the object until it’s actually needed. -
error_condition::failedanderror_condition::messagehave been undeprecated, andoperator bool()now once again returnsfailed(). -
The system category now doesn’t call
generic_category(), to avoid instantiating the object. -
The return value of
default_error_conditionchanges in some cases into anerror_conditionfrom the generic category, instead of from the system category. This happens on POSIX when the inputerror_codeis from the system category and does not correspond to anyerrc_tvalue. -
The interoperability of
error_codeandstd::error_codehas been improved substantially. It is now possible to constructboost::system::error_codefromstd::error_code, and it’s possible to passboost::system::error_codeto functions takingstd::error_code&. -
A stream insertion operator for
error_conditionhas been added.
Changes in Boost 1.76
-
windows_error.hppis no longer deprecated.
Changes in Boost 1.75
-
The platform-specific headers
windows_error.hpp,linux_error.hpp, andcygwin_error.hppemit deprecation messages and are slated for removal. -
The old names for
generic_category()andsystem_category()emit deprecation messages and are slated for removal. -
error_condition::failedis deprecated and is slated for removal.operator bool()forerror_conditionhas been reverted to its old meaning ofvalue() != 0. This is done for compatibility withstd::error_conditionas the next release is expected to improve interoperability with<system_error>even further. Note that this does not affecterror_code::failed, which is still alive and well. -
The overload of
error_condition::messagethat takes a buffer is deprecated and is slated for removal, for the same reasons. Note that this does not affecterror_code::message.
Changes in Boost 1.74
-
operator bool()now returnsfailed()instead ofvalue() != 0.
Changes in Boost 1.69
-
Boost.System is now header-only. A stub library is still built for compatibility, but linking to it is no longer necessary.
-
Even more functions have been marked
constexpr. -
The destructor of
error_categoryis now protected and no longer virtual. This is a potentially breaking change but its impact is expected to be limited. -
error_categorynow has a constructor that accepts a 64 bit identifier, enabling distinct category objects to compare equal. -
The constructors of
error_categoryare now protected. -
A non-allocating, nonthrowing overload of
messagehas been added. -
A virtual function
failedhas been added, allowing categories for which success is not synonymous with 0. -
The deprecated
boost::system::throwsobject has been removed. -
boost::throws()is now deprecated and its use is discouraged. -
The constructor of
system_errortaking a singleerror_codeargument is now explicit. -
system_error::code()now returns by value.
Changes in Boost 1.68
On a C++14 compiler, many Boost.System functions and member functions
are now constexpr, and error_code and error_condition are literal
classes.
In addition to enabling use in constant expressions (and constexpr
functions), this significantly improves the quality of the generated code.
As a result of this change, however, now using Boost.System from C++14
or C++17 code requires that the library be also built with C++14 or
above. This is the default on GCC 6 and newer, but not on GCC 5 or Clang.
One can build Boost for C++14 by passing the cxxstd=14 option to b2.
(Previous versions allowed code built against any C++ standard to link with Boost.System built against any C++ standard. In 1.68, code using any C++ standard can link with Boost.System built with C++14 or above, but if Boost.System is built with C++11 or below, only code also built with C++11 and below can link to it successfully.)
Changes in Boost 1.65
On a C++11 compiler, Boost.System now provides implicit conversions
from boost::system::error_category, error_code, and error_condition
to their standard equivalents from <system_error>.
This allows libraries to expose a C++11 interface and report errors
via std::error_code even when using Boost.System, directly or through a
dependency such as Boost.ASIO.
Design Rationale
error_code and error_condition are designed as value types so
they can be copied without slicing and do not require heap allocation, but
still have polymorphic behavior based on the error category. This is achieved
by abstract base class error_category supplying the polymorphic behavior,
and error_code and error_condition containing a pointer to an object of a
type derived from error_category.
Many of the detailed design decisions were driven by the requirements that users to be able to add additional error categories, and that it be no more difficult to write portable code than system-specific code.
The operator<< overload for error_code eliminates a misleading conversion to
bool in code like cout << ec, where ec is of type error_code. It is also
useful in its own right.
Reference
Use of C++11 and C++14 Features
The library is documented to use several C++11 and C++14 features,
including noexcept, explicit conversion operators and constexpr. The
actual implementation uses C++11 and C++14 features only when they are
available, and otherwise falls back on C++03 features.
Macros
When BOOST_SYSTEM_ENABLE_DEPRECATED is defined, the library provides
deprecated features for compatibility. These features are bound to eventually
disappear.
When BOOST_SYSTEM_USE_UTF8 is defined, on Windows the library returns
UTF-8 messages using code page CP_UTF8 instead of the default CP_ACP.
This macro has no effect on POSIX.
Deprecated Names
In the process of adding Boost.System to the C++11 standard library, the
C++ committee changed some names. To ease transition, Boost.System deprecates
the old names, but will provide them when the macro BOOST_SYSTEM_ENABLE_DEPRECATED is defined.
| Old usage, now deprecated | Replacement |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<boost/system/is_error_code_enum.hpp>
is_error_code_enum
namespace boost {
namespace system {
template<class T>
struct is_error_code_enum { static const bool value = false; };
} // namespace system
} // namespace boost
Users may specialize is_error_code_enum for their error enumeration
types to indicate that they should be eligible for automatic conversions
to error_code. This conversion calls make_error_code(e), which should
be provided in the same namespace as the enumeration type.
<boost/system/is_error_condition_enum.hpp>
is_error_condition_enum
namespace boost {
namespace system {
template<class T>
struct is_error_condition_enum { static const bool value = false; };
} // namespace system
} // namespace boost
Users may specialize is_error_condition_enum for their error enumeration
types to indicate that they should be eligible for automatic conversions
to error_condition. This conversion calls make_error_condition(e), which
should be provided in the same namespace as the enumeration type.
<boost/system/errc.hpp>
errc
namespace boost {
namespace system {
namespace errc {
enum errc_t
{
success = 0,
address_family_not_supported, //EAFNOSUPPORT
address_in_use, //EADDRINUSE
address_not_available, //EADDRNOTAVAIL
already_connected, //EISCONN
argument_list_too_long, //E2BIG
argument_out_of_domain, //EDOM
bad_address, //EFAULT
bad_file_descriptor, //EBADF
bad_message, //EBADMSG
broken_pipe, //EPIPE
connection_aborted, //ECONNABORTED
connection_already_in_progress, //EALREADY
connection_refused, //ECONNREFUSED
connection_reset, //ECONNRESET
cross_device_link, //EXDEV
destination_address_required, //EDESTADDRREQ
device_or_resource_busy, //EBUSY
directory_not_empty, //ENOTEMPTY
executable_format_error, //ENOEXEC
file_exists, //EEXIST
file_too_large, //EFBIG
filename_too_long, //ENAMETOOLONG
function_not_supported, //ENOSYS
host_unreachable, //EHOSTUNREACH
identifier_removed, //EIDRM
illegal_byte_sequence, //EILSEQ
inappropriate_io_control_operation, //ENOTTY
interrupted, //EINTR
invalid_argument, //EINVAL
invalid_seek, //ESPIPE
io_error, //EIO
is_a_directory, //EISDIR
message_size, //EMSGSIZE
network_down, //ENETDOWN
network_reset, //ENETRESET
network_unreachable, //ENETUNREACH
no_buffer_space, //ENOBUFS
no_child_process, //ECHILD
no_link, //ENOLINK
no_lock_available, //ENOLCK
no_message_available, //ENODATA
no_message, //ENOMSG
no_protocol_option, //ENOPROTOOPT
no_space_on_device, //ENOSPC
no_stream_resources, //ENOSR
no_such_device_or_address, //ENXIO
no_such_device, //ENODEV
no_such_file_or_directory, //ENOENT
no_such_process, //ESRCH
not_a_directory, //ENOTDIR
not_a_socket, //ENOTSOCK
not_a_stream, //ENOSTR
not_connected, //ENOTCONN
not_enough_memory, //ENOMEM
not_supported, //ENOTSUP
operation_canceled, //ECANCELED
operation_in_progress, //EINPROGRESS
operation_not_permitted, //EPERM
operation_not_supported, //EOPNOTSUPP
operation_would_block, //EWOULDBLOCK
owner_dead, //EOWNERDEAD
permission_denied, //EACCES
protocol_error, //EPROTO
protocol_not_supported, //EPROTONOSUPPORT
read_only_file_system, //EROFS
resource_deadlock_would_occur, //EDEADLK
resource_unavailable_try_again, //EAGAIN
result_out_of_range, //ERANGE
state_not_recoverable, //ENOTRECOVERABLE
stream_timeout, //ETIME
text_file_busy, //ETXTBSY
timed_out, //ETIMEDOUT
too_many_files_open_in_system, //ENFILE
too_many_files_open, //EMFILE
too_many_links, //EMLINK
too_many_synbolic_link_levels, //ELOOP
value_too_large, //EOVERFLOW
wrong_protocol_type //EPROTOTYPE
};
} // namespace errc
template<> struct is_error_condition_enum<errc::errc_t>
{ static const bool value = true; };
constexpr error_code make_error_code( errc::errc_t e ) noexcept;
constexpr error_condition make_error_condition( errc::errc_t e ) noexcept;
} // namespace system
} // namespace boost
The predefined enumeration type errc::errc_t provides named constants
corresponding to the values of the <cerrno> macros.
constexpr error_condition make_error_condition( errc::errc_t e ) noexcept;
-
- Returns:
-
error_condition( e, generic_category() ).
Since
errc::errc_tprovides a specialization ofis_error_condition_enumand an overload ofmake_error_condition, it can be converted implicitly to anerror_condition. This is typically useful when comparingerror_codevalues returned from APIs to a portable condition, as in the below example: -
void api_function( boost::system::error_code& ec ); void my_function() { boost::system::error_code ec; api_function( ec ); if( ec == boost::system::errc::no_such_file_or_directory ) { // an entity wasn't found (ENOENT) // handle this condition } }
constexpr error_code make_error_code( errc::errc_t e ) noexcept;
-
- Returns:
-
error_code( e, generic_category() ).
In addition to
make_error_condition,errc::errc_tprovides an overload ofmake_error_code. This allows the creation of generic error codes, an operation typically useful when a function needs to signal a generic failure that does not come from an underlying API, such as for instance an out of memory condition: -
void my_api_function( boost::system::error_code& ec ) { void* p = std::malloc( 16 ); if( p == 0 ) { // return ENOMEM ec = make_error_code( boost::system::errc::out_of_memory ); return; } // use p }
<boost/system/error_category.hpp>
error_category
The class error_category defines the base class for types used
to identify the source and encoding of a particular category of error code.
Classes may be derived from error_category to support categories of
errors in addition to those defined in Boost.System.
namespace boost {
namespace system {
class error_category
{
public: // noncopyable
error_category( error_category const & ) = delete;
error_category& operator=( error_category const & ) = delete;
protected:
~error_category() = default;
constexpr error_category() noexcept;
explicit constexpr error_category( unsigned long long id ) noexcept;
public:
virtual const char * name() const noexcept = 0;
virtual error_condition default_error_condition( int ev ) const noexcept;
virtual bool equivalent( int code, const error_condition & condition )
const noexcept;
virtual bool equivalent( const error_code & code, int condition )
const noexcept;
virtual std::string message( int ev ) const = 0;
virtual char const * message( int ev, char * buffer, std::size_t len )
const noexcept;
virtual bool failed( int ev ) const noexcept;
friend constexpr bool operator==( const error_category & lhs,
const error_category & rhs ) noexcept;
friend constexpr bool operator!=( const error_category & lhs,
const error_category & rhs ) noexcept;
friend constexpr bool operator< ( const error_category & lhs,
const error_category & rhs ) noexcept;
operator std::error_category const & () const;
private:
unsigned long long id_; // exposition only
};
} // namespace system
} // namespace boost
Constructors
constexpr error_category() noexcept;
-
- Effects:
-
Initializes
id_to 0. - Remarks:
-
Since equivalence for categories that do not have an identifier is based on comparing object addresses, a user-defined derived category of type
Cthat uses this constructor should ensure that only one object of typeCexists in the program.
explicit constexpr error_category( unsigned long long id ) noexcept;
-
- Effects:
-
Initializes
id_toid. - Remarks:
-
User-defined derived categories that use this constructor are considered equivalent when their identifiers match. Therefore, those categories may have more than one instance existing in a program, but to minimize the possibility of collision, their identifiers must be randomly chosen (at the time the category is implemented, not at runtime). One way of generating a 64 bit random identifier is https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h.
Virtuals
virtual const char * name() const noexcept = 0;
-
- Returns:
-
In derived classes, a character literal naming the error category.
virtual error_condition default_error_condition( int ev ) const noexcept;
-
- Returns:
-
-
In derived classes, an error condition corresponding to
ev. The returned error condition will typically come from the generic category. -
In the default implementation,
error_condition( ev, *this ).
-
virtual bool equivalent( int code, const error_condition & condition )
const noexcept;
-
- Returns:
-
-
In derived classes,
truewhenerror_code( code, *this )is equivalent tocondition. -
In the default implementation,
default_error_condition( code ) == condition.
-
virtual bool equivalent( const error_code & code, int condition )
const noexcept;
-
- Returns:
-
-
In derived classes,
truewhencodeis equivalent toerror_condition( condition, *this ). -
In the default implementation,
*this == code.category() && code.value() == condition.
-
virtual std::string message( int ev ) const = 0;
-
- Returns:
-
In derived classes, a string that describes the error denoted by
ev.
virtual char const * message( int ev, char * buffer, std::size_t len )
const noexcept;
-
- Effects:
-
-
Derived classes should either
-
return a pointer to a character literal describing the error denoted by
ev, or -
copy a string describing the error into
buffer, truncating it tolen-1characters and storing a null terminator, and returnbuffer. Iflenis 0, nothing is copied, but the function still returnsbuffer. Note that whenlenis 0,buffermay benullptr.
-
-
The default implementation calls
message(ev)and copies the result intobuffer, truncating it tolen-1characters and storing a null terminator. Iflenis 0, copies nothing. Returnsbuffer. Ifmessage(ev)throws an exception, the string"Message text unavailable"is used.
-
- Example:
-
const char* my_category::message(int ev, char* buffer, size_t len) const noexcept { switch(ev) { case 0: return "no error"; case 1: return "voltage out of range"; case 2: return "impedance mismatch"; case 31: case 32: case 33: std::snprintf(buffer, len, "component %d failure", ev-30); return buffer; default: std::snprintf(buffer, len, "unknown error %d", ev); return buffer; } }
virtual bool failed( int ev ) const noexcept;
-
- Returns:
-
-
In derived classes,
truewhenevrepresents a failure. -
In the default implementation,
ev != 0.
-
- Remarks:
-
All calls to this function with the same
evmust return the same value.
Comparisons
friend constexpr bool operator==( const error_category & lhs,
const error_category & rhs ) noexcept;
-
- Returns:
-
rhs.id_ == 0? &lhs == &rhs: lhs.id_ == rhs.id_. - Remarks:
-
Two category objects are considered equivalent when they have matching nonzero identifiers, or are the same object.
friend constexpr bool operator!=( const error_category & lhs,
const error_category & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ).
constexpr bool operator< ( const error_category & lhs,
const error_category & rhs ) const noexcept;
-
- Returns:
-
-
If
lhs.id_ < rhs.id_,true; -
Otherwise, if
lhs.id_ > rhs.id_,false; -
Otherwise, if
rhs.id_ != 0,false; -
Otherwise,
std::less<error_category const *>()( &lhs, &rhs ).
-
Conversions
operator std::error_category const & () const;
-
- Returns:
-
A reference to an
std::error_categoryobject corresponding to*this.
<boost/system/system_category.hpp>
system_category
namespace boost {
namespace system {
constexpr const error_category & system_category() noexcept;
} // namespace system
} // namespace boost
constexpr const error_category & system_category() noexcept;
-
- Returns:
-
A reference to a predefined
error_categoryobject identifying errors originating from the operating system.
<boost/system/generic_category.hpp>
generic_category
namespace boost {
namespace system {
constexpr const error_category & generic_category() noexcept;
} // namespace system
} // namespace boost
constexpr const error_category & generic_category() noexcept;
-
- Returns:
-
A reference to a predefined
error_categoryobject identifying portable error codes and conditions.
<boost/system/error_code.hpp>
error_code
The class error_code describes an object used to hold error code
values, such as those originating from the operating system or other
low-level application program interfaces. It’s an adjunct to error reporting
by exception.
namespace boost {
namespace system {
class error_code {
public:
// constructors
constexpr error_code() noexcept;
constexpr error_code( int val, const error_category & cat ) noexcept;
error_code( int val, const error_category & cat,
boost::source_location const * loc ) noexcept;
template<class ErrorCodeEnum>
constexpr error_code( ErrorCodeEnum e ) noexcept;
template<class ErrorCodeEnum>
error_code( ErrorCodeEnum e, boost::source_location const * loc )
noexcept;
error_code( std::error_code const& ec ) noexcept;
// modifiers
constexpr void assign( int val, const error_category & cat ) noexcept;
void assign( int val, const error_category & cat,
boost::source_location const * loc ) noexcept;
template<class ErrorCodeEnum>
constexpr error_code & operator=( ErrorCodeEnum e ) noexcept;
template<class ErrorCodeEnum>
void assign( ErrorCodeEnum e,
boost::source_location const * loc ) noexcept;
constexpr void clear() noexcept;
// observers
constexpr int value() const noexcept;
constexpr const error_category & category() const noexcept;
error_condition default_error_condition() const noexcept;
std::string message() const;
char const * message( char * buffer, std::size_t len ) const noexcept;
constexpr bool failed() const noexcept;
constexpr explicit operator bool() const noexcept;
bool has_location() const noexcept;
boost::source_location const & location() const noexcept;
// comparisons
friend constexpr bool operator==( const error_code & lhs,
const error_code & rhs ) noexcept;
friend constexpr bool operator!=( const error_code & lhs,
const error_code & rhs ) noexcept;
friend constexpr bool operator<( const error_code & lhs,
const error_code & rhs ) noexcept;
friend bool operator==( const error_code & code,
const error_condition & condition ) noexcept;
friend bool operator==( const error_condition & condition,
const error_code & code ) noexcept;
friend bool operator!=( const error_code & code,
const error_condition & condition ) noexcept;
friend bool operator!=( const error_condition & condition,
const error_code & code ) noexcept;
friend bool operator==( const error_code & lhs,
const std::error_code & rhs ) noexcept;
friend bool operator==( const std::error_code & lhs,
const error_code & rhs ) noexcept;
friend bool operator!=( const error_code & lhs,
const std::error_code & rhs ) noexcept;
friend bool operator!=( const std::error_code & lhs,
const error_code & rhs ) noexcept;
template<class E>
friend constexpr bool operator==( const error_code & lhs, E rhs ) noexcept;
template<class E>
friend constexpr bool operator==( E lhs, const error_code & rhs ) noexcept;
template<class E>
friend constexpr bool operator!=( const error_code & lhs, E rhs ) noexcept;
template<class E>
friend constexpr bool operator!=( E lhs, const error_code & rhs ) noexcept;
// conversions
operator std::error_code() const;
operator std::error_code();
template<class T> operator T& (); // only when T=std::error_code
// to_string
std::string to_string() const;
// stream insertion
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<( basic_ostream<charT, traits>& os, const error_code & ec );
// what
std::string what() const;
};
// non-member functions
std::size_t hash_value( const error_code & ec );
} // namespace system
} // namespace boost
Constructors
constexpr error_code() noexcept;
-
- Ensures:
-
value() == 0;category() == system_category();!has_location().
constexpr error_code( int val, const error_category & cat ) noexcept;
-
- Ensures:
-
value() == val;category() == cat;!has_location().
error_code( int val, const error_category & cat,
boost::source_location const * loc ) noexcept;
-
- Requires:
-
locpoints to a validboost::source_locationobject with static storage duration. - Ensures:
-
value() == val;category() == cat;has_location();&location() == loc.
template<class ErrorCodeEnum>
constexpr error_code( ErrorCodeEnum e ) noexcept;
-
- Ensures:
-
*this == make_error_code( e ). - Remarks:
-
This constructor is only enabled when
is_error_code_enum<ErrorCodeEnum>::valueistrue.
template<class ErrorCodeEnum>
error_code( ErrorCodeEnum e, boost::source_location const * loc ) noexcept;
-
- Requires:
-
locpoints to a validboost::source_locationobject with static storage duration. - Ensures:
-
*this == make_error_code( e ). - Remarks:
-
This constructor is only enabled when
is_error_code_enum<ErrorCodeEnum>::valueistrue. Whenmake_error_code( e )is not a default-constructederror_codeand doesn’t wrap astd::error_code,has_location()istrueand&location()isloc.
error_code( std::error_code const & ec ) noexcept;
-
- Effects:
-
Construct an
error_codethat wrapsec. - Remarks:
-
value()andcategory()are unspecified.has_location()isfalse.
Modifiers
constexpr void assign( int val, const error_category & cat ) noexcept;
-
- Effects:
-
*this = error_code( val, cat ).
void assign( int val, const error_category & cat,
boost::source_location const * loc ) noexcept;
-
- Effects:
-
*this = error_code( val, cat, loc ).
template<class ErrorCodeEnum>
constexpr error_code & operator=( ErrorCodeEnum e ) noexcept;
-
- Ensures:
-
*this == make_error_code( e ). - Remarks:
-
This operator is only enabled when
is_error_code_enum<ErrorCodeEnum>::valueistrue.
template<class ErrorCodeEnum>
void assign( ErrorCodeEnum e,
boost::source_location const * loc ) noexcept;
-
- Requires:
-
locpoints to a validboost::source_locationobject with static storage duration. - Effects:
-
*this = error_code( e, loc ). - Remarks:
-
This function is only enabled when
is_error_code_enum<ErrorCodeEnum>::valueistrue.
constexpr void clear() noexcept;
-
- Effects:
-
*this = error_code().
Observers
constexpr int value() const noexcept;
-
- Returns:
-
the error value.
constexpr const error_category & category() const noexcept;
-
- Returns:
-
the error category.
error_condition default_error_condition() const noexcept;
-
- Returns:
-
category().default_error_condition( value() ).
std::string message() const;
-
- Returns:
-
If
*thiswraps astd::error_codeobjectec,ec.message(). Otherwise,category().message( value() ).
char const * message( char * buffer, std::size_t len ) const noexcept;
-
- Effects:
-
If
*thiswraps astd::error_codeobjectec, copies the string returned fromec.message()intobufferand returnsbuffer. Otherwise, returnscategory().message( value(), buffer, len ).
constexpr bool failed() const noexcept;
-
- Returns:
-
If
*thiswraps astd::error_codeobjectec,ec.value() != 0. Otherwise,category().failed( value() ).
constexpr explicit operator bool() const noexcept;
-
- Returns:
-
failed().
bool has_location() const noexcept;
-
- Returns:
-
trueif*thishas been constructed with a pointer to a source location,falseotherwise.
boost::source_location const & location() const noexcept;
-
- Returns:
-
*locif*thishas been constructed with a pointer to a source locationloc, a reference to a default-constructedboost::source_locationotherwise.
Comparisons
friend constexpr bool operator==( const error_code & lhs,
const error_code & rhs ) noexcept;
-
- Returns:
-
If both
lhsandrhswrapstd::error_codeobjectse1ande2,e1 == e2. Otherwise,lhs.value() == rhs.value() && lhs.category() == rhs.category().
friend constexpr bool operator!=( const error_code & lhs,
const error_code & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ).
friend constexpr bool operator<( const error_code & lhs,
const error_code & rhs ) noexcept;
-
- Returns:
-
If both
lhsandrhswrapstd::error_codeobjectse1ande2,e1 < e2. Otherwise,lhs.category() < rhs.category() || (lhs.category() == rhs.category() && lhs.value() < rhs.value()).
friend bool operator==( const error_code & code,
const error_condition & condition ) noexcept;
friend bool operator==( const error_condition & condition,
const error_code & code ) noexcept;
-
- Returns:
-
If
codewraps astd::error_codeobjectec,ec == static_cast<std::error_condition>( condition ). Otherwise,code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() ).
friend bool operator!=( const error_code & lhs,
const error_condition & rhs ) noexcept;
friend bool operator!=( const error_condition & lhs,
const error_code & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ).
friend bool operator==( const error_code & lhs,
const std::error_code & rhs ) noexcept;
-
- Returns:
-
static_cast<std::error_code>(lhs) == rhs.
friend bool operator==( const std::error_code & lhs,
const error_code & rhs ) noexcept;
-
- Returns:
-
lhs == static_cast<std::error_code>(rhs).
friend bool operator!=( const error_code & lhs,
const std::error_code & rhs ) noexcept;
friend bool operator!=( const std::error_code & lhs,
const error_code & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ).
template<class E>
friend constexpr bool operator==( const error_code & lhs, E rhs ) noexcept;
-
- Effects:
-
When
is_error_code_enum<E>::valueistrue, returnslhs == make_error_code(rhs); -
When
is_error_condition_enum<E>::valueistrue, returnslhs == make_error_condition(rhs); -
Otherwise, this overload is disabled.
template<class E>
friend constexpr bool operator==( E lhs, const error_code & rhs ) noexcept;
-
- Effects:
-
When
is_error_code_enum<E>::valueistrue, returnsmake_error_code(lhs) == rhs; -
When
is_error_condition_enum<E>::valueistrue, returnsmake_error_condition(lhs) == rhs; -
Otherwise, this overload is disabled.
template<class E>
friend constexpr bool operator!=( const error_code & lhs, E rhs ) noexcept;
template<class E>
friend constexpr bool operator!=( E lhs, const error_code & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ). - Remarks:
-
These overloads are only enabled when
is_error_code_enum<E>::valueistrueoris_error_condition_enum<E>::valueistrue.
Conversions
operator std::error_code() const;
operator std::error_code();
-
- Returns:
-
If
*thiswraps astd::error_codeobjectec,ec. Otherwise,std::error_code( value(), category() ).
template<class T> operator T&();
-
- Effects:
-
If
*thiswraps astd::error_codeobjectec, returns a reference toec. Otherwise, makes*thiswrapstd::error_code( *this ), then returns a reference to it. - Remarks:
-
This operator is only enabled when
Tisstd::error_code.
to_string
std::string to_string() const;
-
- Returns:
-
If
*thiswraps astd::error_codeobjecte2, a string that is the concatenation of"std:",e2.category().name(),':', and the string representation ofe2.value(). Otherwise, the concatenation ofcategory().name(),':', and the string representation ofvalue().
Stream Insertion
template <class charT, class traits>
std::basic_ostream<charT, traits>&
operator<<( basic_ostream<charT, traits>& os, const error_code & ec );
-
- Effects:
-
os << to_string(). - Returns:
-
os.
what
std::string what() const;
-
- Returns:
-
A string representation of
*this, suitable for logging and diagnostic output. Typically incorporatesmessage(),to_string(), andlocation().to_string()(if available.)
Nonmembers
std::size_t hash_value( const error_code & ec );
-
- Returns:
-
If
ecwraps astd::error_codeobjecte2,std::hash<std::error_code>()(e2). Otherwise, a hash value representingec.
<boost/system/error_condition.hpp>
error_condition
namespace boost {
namespace system {
class error_condition {
public:
// constructors
constexpr error_condition() noexcept;
constexpr error_condition( int val, const error_category & cat ) noexcept;
template <class ErrorConditionEnum>
constexpr error_condition( ErrorConditionEnum e ) noexcept;
// modifiers
constexpr void assign( int val, const error_category & cat ) noexcept;
template<typename ErrorConditionEnum>
constexpr error_condition & operator=( ErrorConditionEnum e ) noexcept;
constexpr void clear() noexcept;
// observers
constexpr int value() const noexcept;
constexpr const error_category & category() const noexcept;
std::string message() const;
char const * message( char * buffer, std::size_t len ) const noexcept;
constexpr bool failed() const noexcept;
constexpr explicit operator bool() const noexcept;
// comparisons
friend constexpr bool operator==( const error_condition & lhs,
const error_condition & rhs ) noexcept;
friend constexpr bool operator!=( const error_condition & lhs,
const error_condition & rhs ) noexcept;
friend constexpr bool operator<( const error_condition & lhs,
const error_condition & rhs ) noexcept;
friend bool operator==( const std::error_code & code,
const error_condition & condition ) noexcept;
friend bool operator==( const error_condition & condition,
const std::error_code & code ) noexcept;
friend bool operator!=( const std::error_code & code,
const error_condition & condition ) noexcept;
friend bool operator!=( const error_condition & condition,
const std::error_code & code ) noexcept;
// conversions
operator std::error_condition() const;
// to_string
std::string to_string() const;
// stream insertion
template <class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<( basic_ostream<charT, traits>& os, const error_condition & en );
};
} // namespace system
} // namespace boost
Constructors
constexpr error_condition() noexcept;
-
- Ensures:
-
value() == 0;category() == generic_category().
constexpr error_condition( int val, const error_category & cat ) noexcept;
-
- Ensures:
-
value() == val;category() == cat.
template <class ErrorConditionEnum>
constexpr error_condition( ErrorConditionEnum e ) noexcept;
-
- Ensures:
-
*this == make_error_condition( e ). - Remarks:
-
This constructor is only enabled when
is_error_condition_enum<ErrorConditionEnum>::valueistrue.
Modifiers
constexpr void assign( int val, const error_category & cat ) noexcept;
-
- Ensures:
-
value() == val;category() == cat.
template <class ErrorConditionEnum>
constexpr error_condition & operator=( ErrorConditionEnum e ) noexcept;
-
- Ensures:
-
*this == make_error_condition( e ). - Remarks:
-
This operator is only enabled when
is_error_condition_enum<ErrorConditionEnum>::valueistrue.
constexpr void clear() noexcept;
-
- Ensures:
-
value() == 0;category() == generic_category().
Observers
constexpr int value() const noexcept;
-
- Returns:
-
the error value.
constexpr const error_category & category() const noexcept;
-
- Returns:
-
the error category.
std::string message() const;
-
- Returns:
-
category().message( value() ).
char const * message( char * buffer, std::size_t len ) const noexcept;
-
- Returns:
-
category().message( value(), buffer, len ).
constexpr bool failed() const noexcept;
-
- Returns:
-
category().failed( value() ).
constexpr explicit operator bool() const noexcept;
-
- Returns:
-
failed().
Comparisons
friend constexpr bool operator==( const error_condition & lhs,
const error_condition & rhs ) noexcept;
-
- Returns:
-
lhs.value() == rhs.value() && lhs.category() == rhs.category().
friend constexpr bool operator!=( const error_condition & lhs,
const error_condition & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ).
friend constexpr bool operator<( const error_condition & lhs,
const error_condition & rhs ) noexcept;
-
- Returns:
-
lhs.category() < rhs.category() || (lhs.category() == rhs.category() && lhs.value() < rhs.value()).
friend bool operator==( const std::error_code & code,
const error_condition & condition ) noexcept;
friend bool operator==( const error_condition & condition,
const std::error_code & code ) noexcept;
-
- Returns:
-
code == static_cast<std::error_condition>( rhs ).
friend constexpr bool operator!=( const std::error_code & lhs,
const error_condition & rhs ) noexcept;
friend constexpr bool operator!=( const error_condition & lhs,
const std::error_code & rhs ) noexcept;
-
- Returns:
-
!( lhs == rhs ).
Conversions
operator std::error_condition() const;
-
- Returns:
-
std::error_condition( value(), category() ).
to_string
std::string to_string() const;
-
- Returns:
-
The concatenation of
"cond:",category().name(),':', and the string representation ofvalue().
Stream Insertion
template <class charT, class traits>
std::basic_ostream<charT, traits>&
operator<<( basic_ostream<charT, traits>& os, const error_condition & en );
-
- Effects:
-
os << en.to_string(). - Returns:
-
os.
<boost/system/system_error.hpp>
system_error
The class system_error describes an exception object used to
report errors that have an associated error_code. Such errors
typically originate from operating system or other low-level
application program interfaces.
namespace boost {
namespace system {
class system_error: public std::runtime_error
{
public:
explicit system_error( error_code ec );
system_error( error_code ec, const char * what_arg );
system_error( error_code ec, const std::string & what_arg );
system_error( int ev, const error_category & ecat );
system_error( int ev, const error_category & ecat,
const char * what_arg );
system_error( int ev, const error_category & ecat,
const std::string & what_arg );
error_code code() const noexcept;
const char * what() const noexcept;
};
} // namespace system
} // namespace boost
Constructors
explicit system_error( error_code ec );
system_error( error_code ec, const char * what_arg );
system_error( error_code ec, const std::string & what_arg );
-
- Ensures:
-
code() == ec.
system_error( int ev, const error_category & ecat,
const char * what_arg );
system_error( int ev, const error_category & ecat,
const std::string & what_arg );
system_error( int ev, const error_category & ecat );
-
- Ensures:
-
code() == error_code( ev, ecat ).
Observers
error_code code() const noexcept;
-
- Returns:
-
ecorerror_code( ev, ecat ), from the constructor, as appropriate.
const char * what() const noexcept;
-
- Returns:
-
A null-terminated character string incorporating the arguments supplied in the constructor, typically of the form
what_arg + ": " + code().message().
<boost/system/result.hpp>
This header defines the class template result<T, E>. Unlike the rest of the library,
it requires C++11.
Synopsis
namespace boost {
namespace system {
// throw_exception_from_error
BOOST_NORETURN inline void throw_exception_from_error( error_code const & e );
// in_place_*
using in_place_value_t = /*unspecified*/;
constexpr in_place_value_t in_place_value{};
using in_place_error_t = /*unspecified*/;
constexpr in_place_error_t in_place_error{};
// result
template<class T, class E = error_code> class result;
template<class E> class result<void, E>;
} // namespace system
} // namespace boost
throw_exception_from_error
The function throw_exception_from_error is called by result<T, E>::value() when
the result holds an error. Its purpose is to throw an exception that represents the
error held in the result.
An implementation for the common and default case where E is error_code is
already provided. It throws system_error(e).
If result<T, E> is used with other error types, the user is expected to provide
an appropriate overload of throw_exception_from_error in the namespace of E.
BOOST_NORETURN inline void throw_exception_from_error( error_code const & e );
-
- Effects:
-
boost::throw_exception( system_error( e ) ).
result<T, E>
result<T, E> stores either a value of type T, or an error of type E. E defaults
to error_code. In a typical use, functions that can fail return result<T>.
namespace boost {
namespace system {
template<class T, class E = error_code> class result
{
public:
// constructors
constexpr result();
template<class... A>
constexpr result( A&&... a );
template<class... A>
constexpr result( in_place_value_t, A&&... a );
template<class... A>
constexpr result( in_place_error_t, A&&... a );
// queries
constexpr bool has_value() const noexcept;
constexpr bool has_error() const noexcept;
constexpr explicit operator bool() const noexcept;
// checked value access
constexpr T& value() & ;
constexpr T const& value() const& ;
constexpr T&& value() && ;
constexpr T const&& value() const&& ;
// unchecked value access
constexpr T* operator->() noexcept;
constexpr T const* operator->() const noexcept;
constexpr T& operator*() & noexcept;
constexpr T const& operator*() const & noexcept;
constexpr T&& operator*() && noexcept;
constexpr T const&& operator*() const && noexcept;
// error access
constexpr E error() const;
// swap
constexpr void swap( result& r );
friend constexpr void swap( result & r1, result & r2 );
// equality
friend constexpr bool operator==( result const & r1, result const & r2 );
friend constexpr bool operator!=( result const & r1, result const & r2 );
};
// stream insertion
template<class Ch, class Tr, class T, class E>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, result<T, E> const & r );
} // namespace system
} // namespace boost
Constructors
constexpr result();
-
- Ensures:
-
*thisholds the valueT(). - Remarks:
-
This constructor is only enabled when
std::is_default_constructible<T>::valueistrue.
template<class... A>
constexpr result( A&&... a );
-
- Effects:
-
-
If
std::is_constructible<T, A…>::value && !std::is_constructible<E, A…>::value, ensures that*thisholds the valueT( std::forward<A>(a)… ). -
If
std::is_constructible<E, A…>::value && !std::is_constructible<T, A…>::value, ensures that*thisholds the errorE( std::forward<A>(a)… ). -
Otherwise, this constructor does not participate in overload resolution.
-
- Remarks:
-
This constructor is only enabled when
sizeof…(T) > 0.
template<class... A>
constexpr result( in_place_value_t, A&&... a );
-
- Ensures:
-
*thisholds the valueT( std::forward<A>(a)… ). - Remarks:
-
This constructor is only enabled when
std::is_constructible<T, A…>::valueistrue.
template<class... A>
constexpr result( in_place_error_t, A&&... a );
-
- Ensures:
-
*thisholds the errorE( std::forward<A>(a)… ). - Remarks:
-
This constructor is only enabled when
std::is_constructible<E, A…>::valueistrue.
Queries
constexpr bool has_value() const noexcept;
-
- Returns:
-
truewhen*thisholds a value,falseotherwise.
constexpr bool has_error() const noexcept;
-
- Returns:
-
!has_value().
constexpr explicit operator bool() const noexcept;
-
- Returns:
-
has_value().
Checked Value Access
constexpr T& value() & ;
constexpr T const& value() const& ;
constexpr T&& value() && ;
constexpr T const&& value() const&& ;
-
- Effects:
-
If
*thisholds a value, returns a reference to it. Otherwise, callsthrow_exception_from_error, passing it a reference to the held error.
Unchecked Value Access
constexpr T* operator->() noexcept;
constexpr T const* operator->() const noexcept;
-
- Returns:
-
If
*thisholds a value, a pointer to it. Otherwise,nullptr.
constexpr T& operator*() & noexcept;
constexpr T const& operator*() const & noexcept;
-
- Requires:
-
*thisholds a value. - Returns:
-
*operator->().
constexpr T&& operator*() && noexcept;
constexpr T const&& operator*() const && noexcept;
-
- Requires:
-
*thisholds a value. - Returns:
-
std::move( *operator->() ).
Error Access
constexpr E error() const;
-
- Effects:
-
If
*thisholds an error, returns it. Otherwise, returnsE().
swap
constexpr void swap( result& r );
-
- Effects:
-
Exchanges the contents of
*thisandr.
friend constexpr void swap( result & r1, result & r2 );
-
- Effects:
-
Exchanges the contents of
r1andr2.
Equality
friend constexpr bool operator==( result const & r1, result const & r2 );
-
- Effects:
-
-
If
r1holds a valuet1andr2holds a valuet2, returnst1 == t2. -
If
r1holds an errore1andr2holds an errore2, returnse1 == e2. -
Otherwise, returns
false.
-
friend constexpr bool operator!=( result const & r1, result const & r2 );
-
- Returns:
-
!( r1 == r2 ).
Stream Insertion
template<class Ch, class Tr, class T, class E>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, result<T, E> const & r );
-
- Effects:
-
-
If
*thisholds a valuet,os << "value:" << t. -
If
*thisholds an errore,os << "error:" << e.
-
- Returns:
-
os.
result<void, E>
namespace boost {
namespace system {
template<class E> class result<void, E>
{
public:
// constructors
constexpr result() noexcept;
template<class... A>
constexpr result( A&&... a );
constexpr result( in_place_value_t ) noexcept;
template<class... A>
constexpr result( in_place_error_t, A&&... a );
// queries
constexpr bool has_value() const noexcept;
constexpr bool has_error() const noexcept;
constexpr explicit operator bool() const noexcept;
// checked value access
constexpr void value() const;
// unchecked value access
constexpr void* operator->() noexcept;
constexpr void const* operator->() const noexcept;
constexpr void operator*() const noexcept;
// error access
constexpr E error() const;
// swap
constexpr void swap( result& r );
friend constexpr void swap( result & r1, result & r2 );
// equality
friend constexpr bool operator==( result const & r1, result const & r2 );
friend constexpr bool operator!=( result const & r1, result const & r2 );
};
// stream insertion
template<class Ch, class Tr, class E>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, result<void, E> const & r );
} // namespace system
} // namespace boost
Constructors
constexpr result() noexcept;
-
- Ensures:
-
*thisholds an unspecified value.
template<class... A>
constexpr result( A&&... a );
-
- Effects:
-
-
If
std::is_constructible<E, A…>::value, ensures that*thisholds the errorE( std::forward<A>(a)… ). -
Otherwise, this constructor does not participate in overload resolution.
-
- Remarks:
-
This constructor is only enabled when
sizeof…(T) > 0.
template<class... A>
constexpr result( in_place_value_t ) noexcept;
-
- Ensures:
-
*thisholds an unspecified value.
template<class... A>
constexpr result( in_place_error_t, A&&... a );
-
- Ensures:
-
*thisholds the errorE( std::forward<A>(a)… ). - Remarks:
-
This constructor is only enabled when
std::is_constructible<E, A…>::valueistrue.
Queries
constexpr bool has_value() const noexcept;
-
- Returns:
-
truewhen*thisholds a value,falseotherwise.
constexpr bool has_error() const noexcept;
-
- Returns:
-
!has_value().
constexpr explicit operator bool() const noexcept;
-
- Returns:
-
has_value().
Checked Value Access
constexpr void value() const;
-
- Effects:
-
If
*thisdoesn’t hold a value, callsthrow_exception_from_error, passing it a reference to the held error.
Unchecked Value Access
constexpr void* operator->() noexcept;
constexpr void const* operator->() const noexcept;
-
- Returns:
-
If
*thisholds a value, a pointer to it. Otherwise,nullptr.
constexpr void operator*() const noexcept;
-
- Requires:
-
*thisholds a value. - Effects:
-
none.
Error Access
constexpr E error() const;
-
- Effects:
-
If
*thisholds an error, returns it. Otherwise, returnsE().
swap
constexpr void swap( result& r );
-
- Effects:
-
Exchanges the contents of
*thisandr.
friend constexpr void swap( result & r1, result & r2 );
-
- Effects:
-
Exchanges the contents of
r1andr2.
Equality
friend constexpr bool operator==( result const & r1, result const & r2 );
-
- Effects:
-
-
If
r1andr2hold values, returnstrue. -
If
r1holds an errore1andr2holds an errore2, returnse1 == e2. -
Otherwise, returns
false.
-
friend constexpr bool operator!=( result const & r1, result const & r2 );
-
- Returns:
-
!( r1 == r2 ).
Stream Insertion
template<class Ch, class Tr, class E>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, result<void, E> const & r );
-
- Effects:
-
-
If
*thisholds a value,os << "value:void". -
If
*thisholds an errore,os << "error:" << e.
-
- Returns:
-
os.
<boost/system.hpp>
This convenience header includes all the headers previously described.
History
N1975, Filesystem Library Proposal for TR2, accepted for Library Technical Report 2 (TR2) at the Berlin meeting, included additional components to supplement the Standard Library’s Diagnostics clause. Since then, these error reporting components have received wider public scrutiny and enhancements have been made to the design. The enhanced version has been used by N2054, Networking Library Proposal for TR2, demonstrating that these error reporting components are useful beyond the original Filesystem Library.
The original proposal viewed error categories as a binary choice between
errno (i.e. POSIX-style) and the native operating system’s error
codes. The proposed components now allow as many additional error categories as
are needed by either implementations or by users. The need to support additional
error categories, for example, occurs in some networking library implementations
because they are built on top of the POSIX getaddrinfo API that
uses error codes not based on errno.
Acknowledgments
Christopher Kohlhoff and Peter Dimov made important contributions to the design. Comments and suggestions were also received from Pavel Vozenilek, Gennaro Prota, Dave Abrahams, Jeff Garland, Iain Hanson, Oliver Kowalke, and Oleg Abrosimov. Christopher Kohlhoff suggested several improvements to the N2066 paper. Johan Nilsson’s comments led to several of the refinements in N2066.
Copyright and License
This documentation is
-
Copyright 2003-2017 Beman Dawes
-
Copyright 2018-2021 Peter Dimov
and is distributed under the Boost Software License, Version 1.0.