Compare commits

..

50 Commits

Author SHA1 Message Date
Peter Dimov
ae341976d4 Avoid pedantic warning for trailing comma in enum 2021-12-10 00:29:17 +02:00
Peter Dimov
29b901c5bb More fixes for implicit int conversions 2021-12-10 00:22:25 +02:00
Peter Dimov
2e1b2dcafb Fix implicit conversion to int errors 2021-12-09 22:26:18 +02:00
Peter Dimov
d0cf08daed Make errc::errc_t a scoped enum 2021-12-09 22:17:47 +02:00
Peter Dimov
91c0dd9a74 Merge pull request #73 from kpushkaryov/patch-1
Fix a typo
2021-11-17 06:24:18 +02:00
Kirill Pushkaryov
189fff42fe Fix a typo 2021-11-17 10:59:03 +07:00
Peter Dimov
3b4045c149 Minor doc update 2021-11-17 04:11:15 +02:00
Peter Dimov
3d877a1fca Update meta/libraries.json 2021-11-11 04:51:03 +02:00
Peter Dimov
128bdf9db2 Minor usage section changes 2021-11-11 04:33:06 +02:00
Peter Dimov
0e84860604 Add another usage subsection 2021-11-11 04:09:49 +02:00
Peter Dimov
83a306f3bf Update introduction 2021-11-10 20:36:57 +02:00
Peter Dimov
7dce2e3f42 Change 'wrapping' to 'adapting' 2021-11-10 18:52:41 +02:00
Peter Dimov
292c6825c6 Add another usage subsection 2021-11-09 22:05:45 +02:00
Peter Dimov
0d90d3d883 Add myimg_category implementation to usage example 2021-11-08 20:50:41 +02:00
Peter Dimov
81fec2b171 Add another usage subsection 2021-11-07 23:45:25 +02:00
Peter Dimov
4e15afe5be Add error handling and programming categories to libraries.json 2021-11-07 20:32:42 +02:00
Peter Dimov
8d1a866920 Add a usage subsection on wrapping zlib errors 2021-11-05 22:05:23 +02:00
Peter Dimov
09466c85b4 Add another usage subsection 2021-11-05 20:38:03 +02:00
Peter Dimov
baef8e50ea Rename 'Usage Examples' to 'Usage', add another subsection 2021-11-05 16:48:33 +02:00
Peter Dimov
5034f11a3a Add usage examples 2021-11-02 03:12:26 +02:00
Peter Dimov
f78b036665 Update #if condition 2021-10-29 21:13:10 +03:00
Ed Catmur
9b0d735040 Add __attribute__((__format__)) to snprintf
This attribute will check format string bugs and is required for clean compile if -Wformat-nonliteral is enabled.
2021-10-29 11:59:03 +01:00
Peter Dimov
bfebaf53d7 Add static_assert to cmake_subdir_test 2021-10-28 23:48:03 +03:00
Peter Dimov
8338e80295 Enable syntax hightlighting 2021-10-28 23:17:20 +03:00
Peter Dimov
2b23aaab16 Add msvc-14.3 to ci.yml 2021-10-28 23:16:53 +03:00
Peter Dimov
7933300b6f Disable test on g++ 4.x because no std::io_errc 2021-10-11 03:30:50 +03:00
Peter Dimov
4ec1e54099 Enable error_code construction from enums specializing std::is_error_code_enum. Fixes #70. 2021-10-11 02:02:22 +03:00
Peter Dimov
5217e58a7d Enable implicit construction for aggregates using {{ ... }} 2021-10-02 22:07:05 +03:00
Peter Dimov
ce37e23491 Protect against dangling references in op* and value() 2021-10-02 19:16:04 +03:00
Peter Dimov
420a262733 Fix warnings_test.cpp 2021-10-02 17:25:31 +03:00
Peter Dimov
e15bccc09b Fix cmake_install_test/main.cpp 2021-10-02 16:57:38 +03:00
Peter Dimov
bb775c071a Update system_error::what to use error_code::what 2021-10-02 15:00:40 +03:00
Peter Dimov
01676ae42f Update documentation 2021-10-02 14:47:07 +03:00
Peter Dimov
eefcc5dcf6 Add error_code::what 2021-10-02 14:41:27 +03:00
Peter Dimov
f2d3a0decf Update documentation 2021-10-02 01:39:06 +03:00
Peter Dimov
0ccf08509b Add a constructor taking ErrorCodeEnum and a source location 2021-10-01 23:04:04 +03:00
Peter Dimov
7a72aee355 Merge branch 'develop' into feature/std-category-2 2021-09-24 23:54:51 +03:00
Peter Dimov
a8df99e927 Use source_location::to_string in system_error::build_message 2021-09-24 20:40:19 +03:00
Peter Dimov
85c7d92302 Avoid instantiating the system category in error_code::operator std::error_code 2021-09-24 15:24:45 +03:00
Peter Dimov
4c201d26b2 Update std_interop_test10 2021-09-24 04:29:29 +03:00
Peter Dimov
1659dfbeba Avoid instantiating generic_category in error_condition::operator std::error_condition 2021-09-24 04:27:08 +03:00
Peter Dimov
d2b8b54356 Do not use std::system_category under MinGW and g++ 4.x 2021-09-21 16:35:40 +03:00
Peter Dimov
41f7ea49cb Do not use std::system_category under VS2013 2021-09-21 16:02:12 +03:00
Peter Dimov
0b22dc595f Merge branch 'develop' into feature/std-category-2 2021-09-21 15:57:56 +03:00
Peter Dimov
aab58b0d5b Add std_interop_test10 2021-09-21 15:57:39 +03:00
Peter Dimov
ad66ea43a3 Revert addition of get_generic_std_category, get_system_std_category (they need this); do not use std::system_category on Cygwin 2021-09-21 15:45:00 +03:00
Peter Dimov
811564f186 Disable failing comparisons in std_interop_test6; stdlibs are at fault 2021-09-21 15:11:19 +03:00
Peter Dimov
a7e4879e55 Fix message comparisons in std_interop_test 2021-09-21 15:06:28 +03:00
Peter Dimov
9b11d864be Add helper functions get_generic_std_category, get_system_std_category 2021-09-21 15:01:44 +03:00
Peter Dimov
cc6a61b6c5 Convert system_category to std::system_category 2021-09-21 05:34:05 +03:00
36 changed files with 2655 additions and 278 deletions

View File

@@ -152,6 +152,10 @@ jobs:
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64

View File

@@ -13,10 +13,13 @@ Beman Dawes, Christopher Kohlhoff, Peter Dimov
:toclevels: 4
:idprefix:
:docinfo: private-footer
:source-highlighter: rouge
:source-language: c++
:leveloffset: +1
include::system/introduction.adoc[]
include::system/usage.adoc[]
include::system/changes.adoc[]
include::system/rationale.adoc[]
include::system/reference.adoc[]

View File

@@ -11,7 +11,7 @@ https://www.boost.org/LICENSE_1_0.txt
## Changes in Boost 1.78
* Added support for source locations to `error_code`.
* Added `error_code::to_string`, `error_condition::to_string`.
* 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>`.

View File

@@ -1,6 +1,6 @@
////
Copyright 2003-2017 Beman Dawes
Copyright 2018 Peter Dimov
Copyright 2018, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
@@ -12,39 +12,67 @@ http://www.boost.org/LICENSE_1_0.txt
# Introduction
:idprefix: intro_
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.
Errors originating from the operating system or other low-level application
program interfaces (APIs) are typically reported via an integer representing
an error code, either by returning the code directly from the function (e.g.
`pthread_mutex_init`) or by using a side channel such as the `errno`
pseudo-variable under POSIX or `GetLastError()` under Windows.
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`.
However, these integer error values can only be interpreted when their source
is known. The value 5 under Windows means `ERROR_ACCESS_DENIED` when returned
by `GetLastError()`, but `EIO` when retrieved from `errno`. And conversely,
the same error condition "access denied" is represented by the value 5 when
returned by `GetLastError()` and 13 (`EACCES`) when retrieved from `errno`.
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.
This means that in order for code to be able to handle errors from both
sources (to retrieve a text message describing the error, or to check whether
the error means "access denied"), it needs to know where the integer error
value originated. For this to be possible, the integer error value needs to
be accompanied by a piece of information identifying the source.
While exceptions are the preferred {cpp} 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.
Boost.System provides a framework in which this is possible. Errors are
represented by a class `error_code` which contains both the error value and
a pointer to their source (called "category"), represented as a class derived
from `error_category`.
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.
The category provides member functions such as `message`, which returns a text
message for a specific error value, and `equivalent`, which can be used to test
whether a specific error value correspond to an error condition such as "access
denied". `error_code` uses these category-provided functions in the
implementation of its `message` and `operator==` member functions.
Boost.System is part of the {cpp}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 <<#ref_deprecated_names,Deprecated Names>> for synonyms provided to prevent
breakage of existing user code.
Boost.System contains two predefined category classes, the generic category
(a reference to which is returned by `generic_category()`) and the system
category (`system_category()`). The generic category represents the error
values of the portable subset of `errno` values defined by the POSIX standard,
whereas the system category is OS dependent. Under POSIX, the system category
represents the `errno` values returned by the OS APIs (a superset of those in
the generic category), whereas under Windows, the system category represents
the error values returned by `GetLastError()`.
The framework is extensible. Users can define their own categories by
deriving a class from `error_category` and implementing a function that
returns a reference to an instance of it. This capability is useful both for
describing library-defined error values, and for adapting existing C API
libraries that return integer error values.
For those who prefer error reporting via exceptions, Boost.System provides
a standard exception class `system_error` that stores an `error_code`.
Boost.System was standardized in {cpp}11 as `<system_error>`. For a while,
the two were equivalent, but Boost.System has evolved since then and now
contains a number of extensions over its standard sibling:
* A non-allocating overload of `message`;
* Support for nonzero error codes meaning success, via the `failed` member
functions;
* Support for 64 bit category identifiers, as a solution to the problem
that sometimes it's not possible to ensure that only one instance of a
category exists in the program;
* Support for attaching source locations (file/line/function) to error codes;
* A class `result<T>` that can be used to return either a value or an error
code from a function;
* Various other minor improvements.
`boost::system::error_code` can be converted to, and constructed from,
`std::error_code`.

View File

@@ -175,7 +175,7 @@ namespace errc {
too_many_files_open_in_system, //ENFILE
too_many_files_open, //EMFILE
too_many_links, //EMLINK
too_many_synbolic_link_levels, //ELOOP
too_many_symbolic_link_levels, //ELOOP
value_too_large, //EOVERFLOW
wrong_protocol_type //EPROTOTYPE
};
@@ -571,9 +571,13 @@ public:
error_code( int val, const error_category & cat,
boost::source_location const * loc ) noexcept;
template <class ErrorCodeEnum>
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
@@ -583,9 +587,13 @@ public:
void assign( int val, const error_category & cat,
boost::source_location const * loc ) noexcept;
template<typename ErrorCodeEnum>
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
@@ -657,9 +665,13 @@ public:
// stream insertion
template <class charT, class traits>
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
@@ -699,7 +711,7 @@ Requires: :: `loc` points to a valid `boost::source_location` object with static
Ensures: :: `value() == val`; `category() == cat`; `has_location()`; `&location() == loc`.
```
template <class ErrorCodeEnum>
template<class ErrorCodeEnum>
constexpr error_code( ErrorCodeEnum e ) noexcept;
```
[none]
@@ -708,6 +720,19 @@ template <class ErrorCodeEnum>
Ensures: :: `*this == make_error_code( e )`.
Remarks: :: This constructor is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
```
template<class ErrorCodeEnum>
error_code( ErrorCodeEnum e, boost::source_location const * loc ) noexcept;
```
[none]
* {blank}
+
Requires: :: `loc` points to a valid `boost::source_location` object with static storage duration.
Ensures: :: `*this == make_error_code( e )`.
Remarks: :: This constructor is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
When `make_error_code( e )` is not a default-constructed `error_code` and doesn't wrap a
`std::error_code`, `has_location()` is `true` and `&location()` is `loc`.
```
error_code( std::error_code const & ec ) noexcept;
```
@@ -737,7 +762,7 @@ void assign( int val, const error_category & cat,
Effects: :: `*this = error_code( val, cat, loc )`.
```
template<typename ErrorCodeEnum>
template<class ErrorCodeEnum>
constexpr error_code & operator=( ErrorCodeEnum e ) noexcept;
```
[none]
@@ -746,6 +771,18 @@ template<typename ErrorCodeEnum>
Ensures: :: `*this == make_error_code( e )`.
Remarks: :: This operator is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
```
template<class ErrorCodeEnum>
void assign( ErrorCodeEnum e,
boost::source_location const * loc ) noexcept;
```
[none]
* {blank}
+
Requires: :: `loc` points to a valid `boost::source_location` object with static storage duration.
Effects: :: `*this = error_code( e, loc )`.
Remarks: :: This function is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
```
constexpr void clear() noexcept;
```
@@ -1021,6 +1058,18 @@ template <class charT, class traits>
Effects: :: `os << to_string()`.
Returns: :: `os`.
#### what
```
std::string what() const;
```
[none]
* {blank}
+
Returns: :: A string representation of `*this`, suitable for logging and
diagnostic output. Typically incorporates `message()`, `to_string()`, and
`location().to_string()` (if available.)
#### Nonmembers
```

1414
doc/system/usage.adoc Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -12,101 +12,124 @@
#include <boost/system/is_error_condition_enum.hpp>
#include <boost/system/detail/cerrno.hpp>
#include <boost/config.hpp>
namespace boost
{
namespace system
{
#define BOOST_SYSTEM_ENUMERATE_ERRC(F, G) \
F(success, 0) \
F(address_family_not_supported, EAFNOSUPPORT) \
F(address_in_use, EADDRINUSE) \
F(address_not_available, EADDRNOTAVAIL) \
F(already_connected, EISCONN) \
F(argument_list_too_long, E2BIG) \
F(argument_out_of_domain, EDOM) \
F(bad_address, EFAULT) \
F(bad_file_descriptor, EBADF) \
F(bad_message, EBADMSG) \
F(broken_pipe, EPIPE) \
F(connection_aborted, ECONNABORTED) \
F(connection_already_in_progress, EALREADY) \
F(connection_refused, ECONNREFUSED) \
F(connection_reset, ECONNRESET) \
F(cross_device_link, EXDEV) \
F(destination_address_required, EDESTADDRREQ) \
F(device_or_resource_busy, EBUSY) \
F(directory_not_empty, ENOTEMPTY) \
F(executable_format_error, ENOEXEC) \
F(file_exists, EEXIST) \
F(file_too_large, EFBIG) \
F(filename_too_long, ENAMETOOLONG) \
F(function_not_supported, ENOSYS) \
F(host_unreachable, EHOSTUNREACH) \
F(identifier_removed, EIDRM) \
F(illegal_byte_sequence, EILSEQ) \
F(inappropriate_io_control_operation, ENOTTY) \
F(interrupted, EINTR) \
F(invalid_argument, EINVAL) \
F(invalid_seek, ESPIPE) \
F(io_error, EIO) \
F(is_a_directory, EISDIR) \
F(message_size, EMSGSIZE) \
F(network_down, ENETDOWN) \
F(network_reset, ENETRESET) \
F(network_unreachable, ENETUNREACH) \
F(no_buffer_space, ENOBUFS) \
F(no_child_process, ECHILD) \
F(no_link, ENOLINK) \
F(no_lock_available, ENOLCK) \
F(no_message_available, ENODATA) \
F(no_message, ENOMSG) \
F(no_protocol_option, ENOPROTOOPT) \
F(no_space_on_device, ENOSPC) \
F(no_stream_resources, ENOSR) \
F(no_such_device_or_address, ENXIO) \
F(no_such_device, ENODEV) \
F(no_such_file_or_directory, ENOENT) \
F(no_such_process, ESRCH) \
F(not_a_directory, ENOTDIR) \
F(not_a_socket, ENOTSOCK) \
F(not_a_stream, ENOSTR) \
F(not_connected, ENOTCONN) \
F(not_enough_memory, ENOMEM) \
F(not_supported, ENOTSUP) \
F(operation_canceled, ECANCELED) \
F(operation_in_progress, EINPROGRESS) \
F(operation_not_permitted, EPERM) \
F(operation_not_supported, EOPNOTSUPP) \
F(operation_would_block, EWOULDBLOCK) \
F(owner_dead, EOWNERDEAD) \
F(permission_denied, EACCES) \
F(protocol_error, EPROTO) \
F(protocol_not_supported, EPROTONOSUPPORT) \
F(read_only_file_system, EROFS) \
F(resource_deadlock_would_occur, EDEADLK) \
F(resource_unavailable_try_again, EAGAIN) \
F(result_out_of_range, ERANGE) \
F(state_not_recoverable, ENOTRECOVERABLE) \
F(stream_timeout, ETIME) \
F(text_file_busy, ETXTBSY) \
F(timed_out, ETIMEDOUT) \
F(too_many_files_open_in_system, ENFILE) \
F(too_many_files_open, EMFILE) \
F(too_many_links, EMLINK) \
F(too_many_symbolic_link_levels, ELOOP) \
F(value_too_large, EOVERFLOW) \
G(wrong_protocol_type, EPROTOTYPE)
namespace errc
{
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) && !defined(BOOST_SYSTEM_ENABLE_DEPRECATED)
enum class errc_t
#else
enum errc_t
#endif
{
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_symbolic_link_levels = ELOOP,
value_too_large = EOVERFLOW,
wrong_protocol_type = EPROTOTYPE
};
#define BOOST_SYSTEM_DEFINE_ERRC(x, y) x = y,
#define BOOST_SYSTEM_DEFINE_ERRC2(x, y) x = y
BOOST_SYSTEM_ENUMERATE_ERRC(BOOST_SYSTEM_DEFINE_ERRC, BOOST_SYSTEM_DEFINE_ERRC2)
#undef BOOST_SYSTEM_DEFINE_ERRC
#undef BOOST_SYSTEM_DEFINE_ERRC2
}; // enum errc_t
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) && !defined(BOOST_SYSTEM_ENABLE_DEPRECATED)
#define BOOST_SYSTEM_SURFACE_ERRC(x, y) BOOST_CONSTEXPR_OR_CONST errc_t x = errc_t::x;
BOOST_SYSTEM_ENUMERATE_ERRC(BOOST_SYSTEM_SURFACE_ERRC, BOOST_SYSTEM_SURFACE_ERRC)
#undef BOOST_SYSTEM_SURFACE_ERRC
#endif
} // namespace errc
#undef BOOST_SYSTEM_ENUMERATE_ERRC
#ifdef BOOST_SYSTEM_ENABLE_DEPRECATED
namespace posix = errc;
@@ -120,7 +143,6 @@ template<> struct is_error_condition_enum<errc::errc_t>
};
} // namespace system
} // namespace boost
#endif // #ifndef BOOST_SYSTEM_DETAIL_ERRC_HPP_INCLUDED

View File

@@ -20,7 +20,6 @@
namespace boost
{
namespace system
{
@@ -91,7 +90,6 @@ inline char const * error_category::message( int ev, char * buffer, std::size_t
}
} // namespace system
} // namespace boost
// interoperability with std::error_code, std::error_condition
@@ -100,36 +98,54 @@ inline char const * error_category::message( int ev, char * buffer, std::size_t
#include <boost/system/detail/std_category.hpp>
inline boost::system::error_category::operator std::error_category const & () const
namespace boost
{
if( id_ == boost::system::detail::generic_category_id )
namespace system
{
inline error_category::operator std::error_category const & () const
{
if( id_ == detail::generic_category_id )
{
// This condition must be the same as the one in error_condition.hpp
#if defined(BOOST_GCC) && BOOST_GCC < 50000
static const boost::system::detail::std_category generic_instance( this, 0x1F4D3 );
return generic_instance;
static const boost::system::detail::std_category generic_instance( this, 0x1F4D3 );
return generic_instance;
#else
return std::generic_category();
return std::generic_category();
#endif
}
if( id_ == boost::system::detail::system_category_id )
if( id_ == detail::system_category_id )
{
static const boost::system::detail::std_category system_instance( this, 0x1F4D7 );
return system_instance;
// This condition must be the same as the one in error_code.hpp
#if defined(__CYGWIN__) || defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER == 1800) || (defined(BOOST_GCC) && BOOST_GCC < 50000)
// Under Cygwin (and MinGW!), std::system_category() is POSIX
// Under VS2013, std::system_category() isn't quite right
static const boost::system::detail::std_category system_instance( this, 0x1F4D7 );
return system_instance;
#else
return std::system_category();
#endif
}
boost::system::detail::std_category* p = ps_.load( std::memory_order_acquire );
detail::std_category* p = ps_.load( std::memory_order_acquire );
if( p != 0 )
{
return *p;
}
boost::system::detail::std_category* q = new detail::std_category( this, 0 );
detail::std_category* q = new detail::std_category( this, 0 );
if( ps_.compare_exchange_strong( p, q, std::memory_order_release, std::memory_order_acquire ) )
{
@@ -142,6 +158,9 @@ inline boost::system::error_category::operator std::error_category const & () co
}
}
} // namespace system
} // namespace boost
#endif // #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
#endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_IMPL_HPP_INCLUDED

View File

@@ -107,10 +107,30 @@ public:
}
template<class ErrorCodeEnum> BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e,
typename detail::enable_if<
is_error_code_enum<ErrorCodeEnum>::value
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
|| std::is_error_code_enum<ErrorCodeEnum>::value
#endif
>::type* = 0 ) BOOST_NOEXCEPT: d1_(), lc_flags_( 0 )
{
*this = make_error_code( e );
}
template<class ErrorCodeEnum> error_code( ErrorCodeEnum e, source_location const * loc,
typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type* = 0 ) BOOST_NOEXCEPT:
d1_(), lc_flags_( 0 )
{
*this = make_error_code( e );
error_code e2 = make_error_code( e );
if( e2.lc_flags_ == 0 || e2.lc_flags_ == 1 )
{
*this = e2;
}
else
{
*this = error_code( e2.d1_.val_, *e2.d1_.cat_, loc );
}
}
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
@@ -143,6 +163,13 @@ public:
return *this;
}
template<typename ErrorCodeEnum>
typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, void>::type
assign( ErrorCodeEnum val, source_location const * loc ) BOOST_NOEXCEPT
{
*this = error_code( val, loc );
}
BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT
{
*this = error_code();
@@ -504,8 +531,16 @@ public:
}
else if( lc_flags_ == 0 )
{
//return std::error_code();
// This condition must be the same as the one in error_category_impl.hpp
#if defined(__CYGWIN__) || defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER == 1800) || (defined(BOOST_GCC) && BOOST_GCC < 50000)
return std::error_code( 0, boost::system::system_category() );
#else
return std::error_code();
#endif
}
else
{
@@ -571,6 +606,23 @@ public:
{
return os << ec.to_string();
}
std::string what() const
{
std::string r = message();
r += " [";
r += to_string();
if( has_location() )
{
r += " at ";
r += location().to_string();
}
r += "]";
return r;
}
};
inline std::size_t hash_value( error_code const & ec )

View File

@@ -84,7 +84,7 @@ public:
template<class ErrorConditionEnum> BOOST_SYSTEM_CONSTEXPR error_condition( ErrorConditionEnum e,
typename detail::enable_if<boost::system::detail::is_same<ErrorConditionEnum, errc::errc_t>::value>::type* = 0) BOOST_NOEXCEPT:
val_( e ), cat_( 0 )
val_( static_cast<int>( e ) ), cat_( 0 )
{
}
@@ -222,7 +222,23 @@ public:
operator std::error_condition () const
{
// This condition must be the same as the one in error_category_impl.hpp
#if defined(BOOST_GCC) && BOOST_GCC < 50000
return std::error_condition( value(), category() );
#else
if( cat_ )
{
return std::error_condition( val_, *cat_ );
}
else
{
return std::error_condition( val_, std::generic_category() );
}
#endif
}
inline friend bool operator==( std::error_code const & lhs, error_condition const & rhs ) BOOST_NOEXCEPT

View File

@@ -49,6 +49,9 @@ inline void snprintf( char * buffer, std::size_t len, char const * format, ... )
#else
#if defined(__GNUC__) && __GNUC__ >= 3
__attribute__((__format__ (__printf__, 3, 4)))
#endif
inline void snprintf( char * buffer, std::size_t len, char const * format, ... )
{
va_list args;

View File

@@ -25,7 +25,7 @@ namespace system
namespace detail
{
inline int system_category_condition_win32( int ev ) BOOST_NOEXCEPT
inline errc::errc_t system_category_condition_win32_( int ev ) BOOST_NOEXCEPT
{
// When using the Windows Runtime, most system errors are reported as HRESULTs.
// We want to map the common Win32 errors to their equivalent error condition,
@@ -138,10 +138,15 @@ inline int system_category_condition_win32( int ev ) BOOST_NOEXCEPT
case WSAETIMEDOUT_: return timed_out;
case WSAEWOULDBLOCK_: return operation_would_block;
default: return -1;
default: return static_cast<errc::errc_t>( -1 );
}
}
inline int system_category_condition_win32( int ev ) BOOST_NOEXCEPT
{
return static_cast<int>( system_category_condition_win32_( ev ) );
}
} // namespace detail
} // namespace system

View File

@@ -32,13 +32,13 @@ namespace errc
// explicit conversion:
BOOST_SYSTEM_CONSTEXPR inline error_code make_error_code( errc_t e ) BOOST_NOEXCEPT
{
return error_code( e, generic_category() );
return error_code( static_cast<int>( e ), generic_category() );
}
// implicit conversion:
BOOST_SYSTEM_CONSTEXPR inline error_condition make_error_condition( errc_t e ) BOOST_NOEXCEPT
{
return error_condition( e, generic_category() );
return error_condition( static_cast<int>( e ), generic_category() );
}
} // namespace errc

View File

@@ -62,35 +62,10 @@ public:
{
}
// explicit, value
template<class A, class En = typename std::enable_if<
std::is_constructible<T, A>::value &&
!std::is_convertible<A, T>::value &&
!std::is_constructible<E, A>::value
>::type>
explicit constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<T, A>::value )
: v_( in_place_value, std::forward<A>(a) )
{
}
// explicit, error
template<class A, class En2 = void, class En = typename std::enable_if<
std::is_constructible<E, A>::value &&
!std::is_convertible<A, E>::value &&
!std::is_constructible<T, A>::value
>::type>
explicit constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<E, A>::value )
: v_( in_place_error, std::forward<A>(a) )
{
}
// implicit, value
template<class A, class En2 = void, class En3 = void, class En = typename std::enable_if<
template<class A = T, typename std::enable_if<
std::is_convertible<A, T>::value &&
!std::is_constructible<E, A>::value
>::type>
!std::is_constructible<E, A>::value, int>::type = 0>
constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<T, A>::value )
: v_( in_place_value, std::forward<A>(a) )
@@ -98,35 +73,32 @@ public:
}
// implicit, error
template<class A, class En2 = void, class En3 = void, class En4 = void, class En = typename std::enable_if<
template<class A = E, class = void, typename std::enable_if<
std::is_convertible<A, E>::value &&
!std::is_constructible<T, A>::value
>::type>
!std::is_constructible<T, A>::value, int>::type = 0>
constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<E, A>::value )
: v_( in_place_error, std::forward<A>(a) )
{
}
// more than one arg, value
// explicit, value
template<class... A, class En = typename std::enable_if<
std::is_constructible<T, A...>::value &&
!std::is_constructible<E, A...>::value &&
sizeof...(A) >= 2
!std::is_constructible<E, A...>::value
>::type>
constexpr result( A&&... a )
explicit constexpr result( A&&... a )
noexcept( std::is_nothrow_constructible<T, A...>::value )
: v_( in_place_value, std::forward<A>(a)... )
{
}
// more than one arg, error
// explicit, error
template<class... A, class En2 = void, class En = typename std::enable_if<
!std::is_constructible<T, A...>::value &&
std::is_constructible<E, A...>::value &&
sizeof...(A) >= 2
std::is_constructible<E, A...>::value
>::type>
constexpr result( A&&... a )
explicit constexpr result( A&&... a )
noexcept( std::is_nothrow_constructible<E, A...>::value )
: v_( in_place_error, std::forward<A>(a)... )
{
@@ -210,12 +182,31 @@ public:
}
}
BOOST_CXX14_CONSTEXPR T&& value() &&
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<std::is_move_constructible<U>::value, T>::type
value() &&
{
return std::move( value() );
}
BOOST_CXX14_CONSTEXPR T const&& value() const&&
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<!std::is_move_constructible<U>::value, T&&>::type
value() &&
{
return std::move( value() );
}
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<std::is_move_constructible<U>::value, T>::type
value() const && = delete;
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<!std::is_move_constructible<U>::value, T const&&>::type
value() const &&
{
return std::move( value() );
}
@@ -274,12 +265,31 @@ public:
return *p;
}
BOOST_CXX14_CONSTEXPR T&& operator*() && noexcept
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<std::is_move_constructible<U>::value, T>::type
operator*() && noexcept(std::is_nothrow_move_constructible<T>::value)
{
return std::move(**this);
}
BOOST_CXX14_CONSTEXPR T const&& operator*() const && noexcept
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<!std::is_move_constructible<U>::value, T&&>::type
operator*() && noexcept
{
return std::move(**this);
}
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<std::is_move_constructible<U>::value, T>::type
operator*() const && noexcept = delete;
template<class U = T>
BOOST_CXX14_CONSTEXPR
typename std::enable_if<!std::is_move_constructible<U>::value, T const&&>::type
operator*() const && noexcept
{
return std::move(**this);
}

View File

@@ -8,7 +8,6 @@
#include <boost/system/errc.hpp>
#include <boost/system/detail/error_code.hpp>
#include <boost/system/detail/snprintf.hpp>
#include <string>
#include <stdexcept>
#include <cassert>
@@ -26,14 +25,6 @@ private:
private:
static std::string to_string( int v )
{
char buffer[ 32 ];
detail::snprintf( buffer, sizeof( buffer ), "%d", v );
return buffer;
}
static std::string build_message( char const * prefix, error_code const & ec )
{
std::string r;
@@ -44,32 +35,7 @@ private:
r += ": ";
}
r += ec.message();
if( ec.has_location() )
{
r += " [";
r += ec.to_string();
r += " at ";
boost::source_location loc = ec.location();
r += loc.file_name();
r += ':';
r += to_string( loc.line() );
if( loc.column() != 0 )
{
r += ':';
r += to_string( loc.column() );
}
r += " in function '";
r += loc.function_name();
r += "\']";
}
r += ec.what();
return r;
}

View File

@@ -4,9 +4,14 @@
"authors": [
"Beman Dawes"
],
"description": "Operating system support, including the diagnostics support that will be part of the C++0x standard library.",
"maintainers": [
"Peter Dimov <pdimov -at- gmail.com>"
],
"description": "Extensible error reporting.",
"category": [
"System"
"System",
"Error-handling",
"Programming"
],
"cxxstd": "03"
}

View File

@@ -104,6 +104,13 @@ boost_test(TYPE run SOURCES ec_location_test.cpp)
boost_test(TYPE run SOURCES error_condition_test3.cpp)
boost_test(TYPE run SOURCES error_code_test2.cpp)
boost_test(TYPE run SOURCES system_error_test2.cpp)
boost_test(TYPE run SOURCES std_interop_test10.cpp)
boost_test(TYPE run SOURCES ec_location_test2.cpp)
boost_test(TYPE run SOURCES ec_what_test.cpp)
boost_test(TYPE run SOURCES system_error_test3.cpp)
boost_test(TYPE run SOURCES std_interop_test11.cpp)
# result
@@ -120,3 +127,6 @@ boost_test(TYPE run SOURCES result_value_access.cpp)
boost_test(TYPE run SOURCES result_error_access.cpp)
boost_test(TYPE run SOURCES result_swap.cpp)
boost_test(TYPE run SOURCES result_eq.cpp)
boost_test(TYPE run SOURCES result_range_for.cpp)
boost_test(TYPE run SOURCES result_value_construct2.cpp)
boost_test(TYPE run SOURCES result_error_construct2.cpp)

View File

@@ -73,8 +73,8 @@ system-run failed_constexpr_test.cpp ;
# Quick (CI) test
run quick.cpp ;
compile warnings_test.cpp
: <warnings>pedantic
run warnings_test.cpp
: : : <warnings>pedantic
<toolset>msvc:<warnings-as-errors>on
<toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on ;
@@ -126,6 +126,13 @@ run ec_location_test.cpp ;
run error_condition_test3.cpp ;
run error_code_test2.cpp ;
run system_error_test2.cpp ;
run std_interop_test10.cpp ;
run ec_location_test2.cpp ;
run ec_what_test.cpp ;
run system_error_test3.cpp ;
run std_interop_test11.cpp ;
# result
@@ -144,3 +151,6 @@ run result_value_access.cpp : : : $(CPP11) ;
run result_error_access.cpp : : : $(CPP11) ;
run result_swap.cpp : : : $(CPP11) <toolset>gcc-10:<cxxflags>"-Wno-maybe-uninitialized" ;
run result_eq.cpp : : : $(CPP11) ;
run result_range_for.cpp : : : $(CPP11) ;
run result_value_construct2.cpp : : : $(CPP11) ;
run result_error_construct2.cpp : : : $(CPP11) ;

View File

@@ -40,5 +40,5 @@ int main()
boost::system::system_error x( bc, "prefix" );
BOOST_TEST_EQ( x.code(), bc );
BOOST_TEST_EQ( std::string( x.what() ), "prefix: " + bc.message() );
BOOST_TEST_EQ( std::string( x.what() ), "prefix: " + bc.what() );
}

View File

@@ -12,6 +12,7 @@ add_subdirectory(../../../config boostorg/config)
add_subdirectory(../../../core boostorg/core)
add_subdirectory(../../../mp11 boostorg/mp11)
add_subdirectory(../../../predef boostorg/predef)
add_subdirectory(../../../static_assert boostorg/static_assert)
add_subdirectory(../../../throw_exception boostorg/throw_exception)
add_subdirectory(../../../variant2 boostorg/variant2)
add_subdirectory(../../../winapi boostorg/winapi)

287
test/ec_location_test2.cpp Normal file
View File

@@ -0,0 +1,287 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/system.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cerrno>
namespace sys = boost::system;
enum E
{
none = 0,
einval = EINVAL
};
namespace boost
{
namespace system
{
template<> struct is_error_code_enum< ::E >
{
static const bool value = true;
};
} // namespace system
} // namespace boost
sys::error_code make_error_code( E e )
{
return e == 0? sys::error_code(): sys::error_code( e, sys::generic_category() );
}
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
enum E2
{
e2inval = EINVAL
};
namespace boost
{
namespace system
{
template<> struct is_error_code_enum< ::E2 >
{
static const bool value = true;
};
} // namespace system
} // namespace boost
std::error_code make_error_code( E2 e )
{
return std::error_code( e, std::generic_category() );
}
#endif
int main()
{
{
sys::error_code ec( einval );
BOOST_TEST_EQ( ec.value(), EINVAL );
BOOST_TEST_EQ( &ec.category(), &sys::generic_category() );
BOOST_TEST( ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
sys::error_code ec( einval, &loc );
BOOST_TEST_EQ( ec.value(), EINVAL );
BOOST_TEST_EQ( &ec.category(), &sys::generic_category() );
BOOST_TEST( ec.failed() );
BOOST_TEST( ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 77 );
}
{
sys::error_code ec( none );
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
sys::error_code ec( none, &loc );
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
ec = sys::error_code( einval, &loc );
BOOST_TEST_EQ( ec.value(), EINVAL );
BOOST_TEST_EQ( &ec.category(), &sys::generic_category() );
BOOST_TEST( ec.failed() );
BOOST_TEST( ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 127 );
}
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
ec = sys::error_code( none, &loc );
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
ec.assign( einval, &loc );
BOOST_TEST_EQ( ec.value(), EINVAL );
BOOST_TEST_EQ( &ec.category(), &sys::generic_category() );
BOOST_TEST( ec.failed() );
BOOST_TEST( ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 175 );
}
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
ec.assign( none, &loc );
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
{
sys::error_code ec( e2inval );
BOOST_TEST_EQ( ec, std::error_code( EINVAL, std::generic_category() ) );
BOOST_TEST( ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
sys::error_code ec( e2inval, &loc );
BOOST_TEST_EQ( ec, std::error_code( EINVAL, std::generic_category() ) );
BOOST_TEST( ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
ec = sys::error_code( e2inval, &loc );
BOOST_TEST_EQ( ec, std::error_code( EINVAL, std::generic_category() ) );
BOOST_TEST( ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST_EQ( &ec.category(), &sys::system_category() );
BOOST_TEST( !ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
ec.assign( e2inval, &loc );
BOOST_TEST_EQ( ec, std::error_code( EINVAL, std::generic_category() ) );
BOOST_TEST( ec.failed() );
BOOST_TEST( !ec.has_location() );
BOOST_TEST_EQ( ec.location().line(), 0 );
}
#endif
return boost::report_errors();
}

91
test/ec_what_test.cpp Normal file
View File

@@ -0,0 +1,91 @@
// Copyright 2020, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/system/error_code.hpp>
#include <boost/system/generic_category.hpp>
#include <boost/system/system_category.hpp>
#include <boost/core/lightweight_test.hpp>
namespace sys = boost::system;
int main()
{
{
sys::error_code ec;
BOOST_TEST_EQ( ec.value(), 0 );
BOOST_TEST( ec.category() == sys::system_category() );
BOOST_TEST_EQ( ec.what(), ec.message() + " [system:0]" );
}
{
sys::error_code ec( 5, sys::generic_category() );
BOOST_TEST_EQ( ec.value(), 5 );
BOOST_TEST( ec.category() == sys::generic_category() );
BOOST_TEST_EQ( ec.what(), ec.message() + " [generic:5]" );
}
{
sys::error_code ec( 5, sys::system_category() );
BOOST_TEST_EQ( ec.value(), 5 );
BOOST_TEST( ec.category() == sys::system_category() );
BOOST_TEST_EQ( ec.what(), ec.message() + " [system:5]" );
}
{
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
sys::error_code ec( 5, sys::generic_category(), &loc );
BOOST_TEST_EQ( ec.value(), 5 );
BOOST_TEST( ec.category() == sys::generic_category() );
BOOST_TEST_EQ( &ec.location(), &loc );
BOOST_TEST_EQ( ec.what(), ec.message() + " [generic:5 at " + loc.to_string() + "]" );
}
{
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
sys::error_code ec( 5, sys::system_category(), &loc );
BOOST_TEST_EQ( ec.value(), 5 );
BOOST_TEST( ec.category() == sys::system_category() );
BOOST_TEST_EQ( &ec.location(), &loc );
BOOST_TEST_EQ( ec.what(), ec.message() + " [system:5 at " + loc.to_string() + "]" );
}
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
{
std::error_code ec;
sys::error_code ec2( ec );
BOOST_TEST_EQ( ec2.what(), ec2.message() + " [std:system:0]" );
}
{
std::error_code ec( 5, std::generic_category() );
sys::error_code ec2( ec );
BOOST_TEST_EQ( ec2.what(), ec2.message() + " [std:generic:5]" );
}
{
std::error_code ec( 5, std::system_category() );
sys::error_code ec2( ec );
BOOST_TEST_EQ( ec2.what(), ec2.message() + " [std:system:5]" );
}
#endif
return boost::report_errors();
}

View File

@@ -165,7 +165,7 @@ int main( int, char ** )
econd = ec.default_error_condition();
BOOST_TEST( econd.value() == static_cast<int>(errc::permission_denied) );
BOOST_TEST( econd.category() == generic_category() );
BOOST_TEST( econd == error_condition( errc::permission_denied, generic_category() ) );
BOOST_TEST( econd == error_condition( static_cast<int>(errc::permission_denied), generic_category() ) );
BOOST_TEST( econd == errc::permission_denied );
BOOST_TEST( errc::permission_denied == econd );
BOOST_TEST( ec == errc::permission_denied );
@@ -244,35 +244,35 @@ int main( int, char ** )
ec = error_code( ERROR_ACCESS_DENIED, system_category() );
BOOST_TEST( ec.value() == ERROR_ACCESS_DENIED );
BOOST_TEST( ec == errc::permission_denied );
BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
BOOST_TEST( ec.default_error_condition().value() == static_cast<int>(errc::permission_denied) );
BOOST_TEST( ec.default_error_condition().category() == generic_category() );
// test the second entry in the decoder table:
ec = error_code( ERROR_ALREADY_EXISTS, system_category() );
BOOST_TEST( ec.value() == ERROR_ALREADY_EXISTS );
BOOST_TEST( ec == errc::file_exists );
BOOST_TEST( ec.default_error_condition().value() == errc::file_exists );
BOOST_TEST( ec.default_error_condition().value() == static_cast<int>(errc::file_exists) );
BOOST_TEST( ec.default_error_condition().category() == generic_category() );
// test the third entry in the decoder table:
ec = error_code( ERROR_BAD_UNIT, system_category() );
BOOST_TEST( ec.value() == ERROR_BAD_UNIT );
BOOST_TEST( ec == errc::no_such_device );
BOOST_TEST( ec.default_error_condition().value() == errc::no_such_device );
BOOST_TEST( ec.default_error_condition().value() == static_cast<int>(errc::no_such_device) );
BOOST_TEST( ec.default_error_condition().category() == generic_category() );
// test the last non-Winsock entry in the decoder table:
ec = error_code( ERROR_WRITE_PROTECT, system_category() );
BOOST_TEST( ec.value() == ERROR_WRITE_PROTECT );
BOOST_TEST( ec == errc::permission_denied );
BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
BOOST_TEST( ec.default_error_condition().value() == static_cast<int>(errc::permission_denied) );
BOOST_TEST( ec.default_error_condition().category() == generic_category() );
// test the last Winsock entry in the decoder table:
ec = error_code( WSAEWOULDBLOCK, system_category() );
BOOST_TEST( ec.value() == WSAEWOULDBLOCK );
BOOST_TEST( ec == errc::operation_would_block );
BOOST_TEST( ec.default_error_condition().value() == errc::operation_would_block );
BOOST_TEST( ec.default_error_condition().value() == static_cast<int>(errc::operation_would_block) );
BOOST_TEST( ec.default_error_condition().category() == generic_category() );
// test not-in-table condition:
@@ -285,11 +285,11 @@ int main( int, char ** )
std::cout << "POSIX tests...\n";
ec = error_code( EACCES, system_category() );
BOOST_TEST( ec == error_code( errc::permission_denied, system_category() ) );
BOOST_TEST( error_code( errc::permission_denied, system_category() ) == ec );
BOOST_TEST( ec == error_code( static_cast<int>(errc::permission_denied), system_category() ) );
BOOST_TEST( error_code( static_cast<int>(errc::permission_denied), system_category() ) == ec );
BOOST_TEST( ec == errc::permission_denied );
BOOST_TEST( errc::permission_denied == ec );
BOOST_TEST( ec.default_error_condition().value() == errc::permission_denied );
BOOST_TEST( ec.default_error_condition().value() == static_cast<int>(errc::permission_denied) );
BOOST_TEST( ec.default_error_condition().category() == generic_category() );
#endif

View File

@@ -118,7 +118,7 @@ namespace boost
boost::system::error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT
{
return ev == boo_boo
? boost::system::error_condition( boost::system::errc::io_error,
? boost::system::error_condition( static_cast<int>( boost::system::errc::io_error ),
boost::system::generic_category() )
: boost::system::error_condition( ev,
boost::lib3::lib3_error_category );
@@ -180,7 +180,7 @@ namespace lib4
boost::system::error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT
{
return ev == boo_boo.value()
? boost::system::error_condition( boost::system::errc::io_error,
? boost::system::error_condition( static_cast<int>( boost::system::errc::io_error ),
boost::system::generic_category() )
: boost::system::error_condition( ev, lib4::lib4_error_category );
}

View File

@@ -18,7 +18,7 @@ struct foo
foo()
{
boost::system::error_code ec;
BOOST_TEST_NE( ec, boost::system::errc::permission_denied );
BOOST_TEST( ec != boost::system::errc::permission_denied );
}
} f;

View File

@@ -37,7 +37,7 @@ int main()
boost::system::system_error x( bc, "prefix" );
BOOST_TEST_EQ( x.code(), bc );
BOOST_TEST_EQ( std::string( x.what() ), "prefix: " + bc.message() );
BOOST_TEST_EQ( std::string( x.what() ), "prefix: " + bc.what() );
return boost::report_errors();
}

View File

@@ -0,0 +1,57 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/system/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <string>
using namespace boost::system;
struct X
{
int a, b;
};
result<X> fx1()
{
return {{ EINVAL, generic_category() }};
}
struct Y
{
std::string v;
};
struct E
{
int v;
};
result<Y, E> fy1()
{
return {{ 42 }};
}
int main()
{
{
result<X> r = fx1();
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code( EINVAL, generic_category() ) );
}
{
result<Y, E> r = fy1();
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v, 42 );
}
return boost::report_errors();
}

30
test/result_range_for.cpp Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/system/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <vector>
using namespace boost::system;
result<std::vector<int>> f()
{
return std::vector<int>{ 1, 2, 3 };
}
int main()
{
{
int s = 0;
for( int x: f().value() )
{
s += x;
}
BOOST_TEST_EQ( s, 6 );
}
return boost::report_errors();
}

View File

@@ -0,0 +1,152 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/system/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <vector>
#include <string>
using namespace boost::system;
struct X
{
int a;
};
struct Y
{
int a, b;
};
struct E
{
std::string v;
};
result<X> fx0()
{
return {};
}
result<X> fx1()
{
return {{ 1 }};
}
result<Y> fy0()
{
return {};
}
result<Y> fy2()
{
return {{ 1, 2 }};
}
result<X, E> fxe0()
{
return {};
}
result<X, E> fxe1()
{
return {{ 1 }};
}
result<std::vector<int>> fv0()
{
return {};
}
result<std::vector<int>> fv1()
{
return {{ 1 }};
}
result<std::vector<int>> fv2()
{
return {{ 1, 2 }};
}
int main()
{
{
result<X> r = fx0();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->a, 0 );
}
{
result<X> r = fx1();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->a, 1 );
}
{
result<Y> r = fy0();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->a, 0 );
BOOST_TEST_EQ( r->b, 0 );
}
{
result<Y> r = fy2();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->a, 1 );
BOOST_TEST_EQ( r->b, 2 );
}
{
result<X, E> r = fxe0();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->a, 0 );
}
{
result<X, E> r = fxe1();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->a, 1 );
}
{
result<std::vector<int>> r = fv0();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->size(), 0 );
}
{
result<std::vector<int>> r = fv1();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->size(), 1 );
BOOST_TEST_EQ( r->at(0), 1 );
}
{
result<std::vector<int>> r = fv2();
BOOST_TEST( r.has_value() );
BOOST_TEST_EQ( r->size(), 2 );
BOOST_TEST_EQ( r->at(0), 1 );
BOOST_TEST_EQ( r->at(1), 2 );
}
return boost::report_errors();
}

View File

@@ -83,34 +83,13 @@ static void test_system_category()
BOOST_TEST_CSTR_EQ( bt.name(), st.name() );
for( int ev = 1; ev < 6; ++ev )
{
int ev = 5;
BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
std::string bm = bt.message( ev );
std::string sm = st.message( ev );
{
boost::system::error_code bc( ev, bt );
BOOST_TEST_EQ( bc.value(), ev );
BOOST_TEST_EQ( &bc.category(), &bt );
std::error_code sc( bc );
BOOST_TEST_EQ( sc.value(), ev );
BOOST_TEST_EQ( &sc.category(), &st );
}
{
boost::system::error_condition bn = bt.default_error_condition( ev );
BOOST_TEST( bt.equivalent( ev, bn ) );
std::error_condition sn( bn );
BOOST_TEST( st.equivalent( ev, sn ) );
}
}
{
int ev = 4;
BOOST_TEST_EQ( bt.message( ev ), st.message( ev ) );
// We strip whitespace and the trailing dot, MSVC not so much
BOOST_TEST_EQ( bm, sm.substr( 0, bm.size() ) );
{
boost::system::error_code bc( ev, bt );

View File

@@ -0,0 +1,66 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/system/error_code.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#include <cerrno>
#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" )
int main() {}
#else
#include <system_error>
int main()
{
{
boost::system::error_code e1;
boost::system::error_code e2( 0, boost::system::system_category() );
BOOST_TEST_EQ( e1, e2 );
std::error_code e3( e1 );
std::error_code e4( e2 );
BOOST_TEST_EQ( e3, e4 );
}
{
boost::system::error_code e1;
std::error_code e2( e1 );
std::error_code e3( e1.value(), e1.category() );
BOOST_TEST_EQ( e2, e3 );
}
{
boost::system::error_condition e1;
boost::system::error_condition e2( 0, boost::system::generic_category() );
BOOST_TEST_EQ( e1, e2 );
std::error_condition e3( e1 );
std::error_condition e4( e2 );
BOOST_TEST( e3 == e4 );
}
{
boost::system::error_condition e1;
std::error_condition e2( e1 );
std::error_condition e3( e1.value(), e1.category() );
BOOST_TEST( e2 == e3 );
}
return boost::report_errors();
}
#endif

View File

@@ -0,0 +1,47 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/system/error_code.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#include <boost/config.hpp>
#include <ios>
#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
BOOST_PRAGMA_MESSAGE( "Skipping test, BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined" )
int main() {}
#elif defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 50000
BOOST_PRAGMA_MESSAGE( "Skipping test, BOOST_LIBSTDCXX_VERSION < 50000" )
int main() {}
#else
#include <system_error>
int main()
{
{
boost::system::error_code ec = std::io_errc::stream;
BOOST_TEST( ec == std::io_errc::stream );
BOOST_TEST_NOT( ec != std::io_errc::stream );
ec.clear();
BOOST_TEST_NOT( ec == std::io_errc::stream );
BOOST_TEST( ec != std::io_errc::stream );
ec = std::io_errc::stream;
BOOST_TEST( ec == std::io_errc::stream );
BOOST_TEST_NOT( ec != std::io_errc::stream );
}
return boost::report_errors();
}
#endif

View File

@@ -30,6 +30,11 @@ int main()
BOOST_TEST_EQ( e2, e1 );
BOOST_TEST_NOT( e2 != e1 );
#if defined(_LIBCPP_VERSION)
// Under MS STL and libstdc++, std::error_code() does not compare
// equal to std::error_condition(). Go figure.
BOOST_TEST_EQ( e2, en );
BOOST_TEST_NOT( e2 != en );
@@ -37,6 +42,8 @@ int main()
BOOST_TEST_EQ( e3, en );
BOOST_TEST_NOT( e3 != en );
#endif
}
{
@@ -51,6 +58,8 @@ int main()
BOOST_TEST_EQ( e2, e1 );
BOOST_TEST_NOT( e2 != e1 );
#if defined(_LIBCPP_VERSION)
BOOST_TEST_EQ( e2, en );
BOOST_TEST_NOT( e2 != en );
@@ -58,6 +67,8 @@ int main()
BOOST_TEST_EQ( e3, en );
BOOST_TEST_NOT( e3 != en );
#endif
}
{

View File

@@ -81,27 +81,25 @@ int main( int, char *[] )
system_error c6_0( 0, system_category(), "c6_0" );
system_error c6_1( 1, system_category(), "c6_1" );
TEST( c1_0, 0, "The operation completed successfully" );
TEST( c1_1, 1, "Incorrect function" );
TEST( c1_2u, 2, "The system cannot find the file specified" );
TEST( c1_0, 0, "The operation completed successfully [system:0]" );
TEST( c1_1, 1, "Incorrect function [system:1]" );
TEST( c1_2u, 2, "The system cannot find the file specified [system:2]" );
TEST( c2_0, 0, "c2_0: The operation completed successfully" );
TEST( c2_1, 1, "c2_1: Incorrect function" );
TEST( c2_0, 0, "c2_0: The operation completed successfully [system:0]" );
TEST( c2_1, 1, "c2_1: Incorrect function [system:1]" );
TEST( c3_0, 0, "c3_0: The operation completed successfully" );
TEST( c3_1, 1, "c3_1: Incorrect function" );
TEST( c3_0, 0, "c3_0: The operation completed successfully [system:0]" );
TEST( c3_1, 1, "c3_1: Incorrect function [system:1]" );
TEST( c4_0, 0, "The operation completed successfully" );
TEST( c4_1, 1, "Incorrect function" );
TEST( c4_2u, 2, "The system cannot find the file specified" );
TEST( c4_0, 0, "The operation completed successfully [system:0]" );
TEST( c4_1, 1, "Incorrect function [system:1]" );
TEST( c4_2u, 2, "The system cannot find the file specified [system:2]" );
TEST( c5_0, 0, "c5_0: The operation completed successfully" );
TEST( c5_1, 1, "c5_1: Incorrect function" );
TEST( c5_0, 0, "c5_0: The operation completed successfully [system:0]" );
TEST( c5_1, 1, "c5_1: Incorrect function [system:1]" );
TEST( c6_0, 0, "c6_0: The operation completed successfully" );
TEST( c6_1, 1, "c6_1: Incorrect function" );
TEST( c6_0, 0, "c6_0: The operation completed successfully [system:0]" );
TEST( c6_1, 1, "c6_1: Incorrect function [system:1]" );
return ::boost::report_errors();
}

View File

@@ -0,0 +1,42 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/system/system_error.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cerrno>
namespace sys = boost::system;
int main()
{
{
sys::error_code ec( 5, sys::generic_category() );
sys::system_error x1( ec );
BOOST_TEST_EQ( std::string( x1.what() ), ec.what() );
}
{
BOOST_STATIC_CONSTEXPR boost::source_location loc = BOOST_CURRENT_LOCATION;
sys::error_code ec( 5, sys::system_category(), &loc );
sys::system_error x1( ec, "prefix" );
BOOST_TEST_EQ( std::string( x1.what() ), "prefix: " + ec.what() );
}
{
sys::system_error x1( 5, sys::generic_category() );
BOOST_TEST_EQ( std::string( x1.what() ), sys::error_code( 5, sys::generic_category() ).what() );
}
{
sys::system_error x1( 5, sys::system_category(), "prefix" );
BOOST_TEST_EQ( std::string( x1.what() ), "prefix: " + sys::error_code( 5, sys::system_category() ).what() );
}
return boost::report_errors();
}

View File

@@ -46,7 +46,7 @@ int main()
boost::system::system_error x( bc, "prefix" );
BOOST_TEST_EQ( x.code(), bc );
BOOST_TEST_EQ( std::string( x.what() ), "prefix: " + bc.message() );
BOOST_TEST_EQ( std::string( x.what() ), "prefix: " + bc.what() );
return boost::report_errors();
}