From 1bb5b95ebd27de49dc50980d0ac742ce1461563c Mon Sep 17 00:00:00 2001
From: Beman error_condition
constructors
Class error_condition
modifiers
Class error_condition
observers
- throws
object
- Semantics of throws
object
+ Function boost::throws()
Non-member functions
Header <boost/system/system_error.hpp>
Class system_error
@@ -316,8 +315,12 @@ fixed by globally adding () to these names to turn them into function calls.
The value of each errc_t
constant shall be the same as the
value of the <cerrno>
macro shown in the above synopsis.
int
) that can occur with bool
are not allowed,
eliminating some sources of user error. One possible implementation choice for
this type is pointer to member. --end note ]
-
- throws
objectextern error_code throws;-
The predefined error_code
object throws
is supplied
-for use as a "throw on error" tag.
throws
objectFunctions that specify an argument in the form error_code& ec=throws
,
-with appropriate namespace qualifiers, have the following error handling
-semantics:
-Postconditions:
---If
-&ec != &throws
and an error occurred:-
-- -
ec.value()
returns the implementation specific error - number for the particular error that occurred.- -
ec.category()
returns the- error_category
forec.value()
.if
-&ec != &throws
and an error did not occur,ec.clear()
.Throws:
--If an error occurs and
-&ec == &throws
, throws an exception of type -system_error
or of a type - derived fromsystem_error
. The - exception'scode()
member function returns a reference to an -error_code
object with the behavior specified in - Postconditions.
bool operator==( const error_code & lhs, const error_code & rhs ) noexcept;@@ -736,6 +709,37 @@ bool operator!=( const error_condition & condition, const error_code & c
Returns: A hash value representing ec
.
boost::throws()
system::error_code& throws();+
++Returns: A
+system::error_code
reference +for use in some user-defined function signature as a "throw on error" tag.Remark: The only valid use for the returned reference is to test its +address for equality or inequality to the address of the reference returned by +another call to throws(). The returned reference itself has been poisoned so +that an attempt to dereference it will fail.
+[Example: Example of a function that uses the
+throws()
idiom:++int divide(int dividend, int divisor, + boost::system::error_code& ec = boost::throws()) +{ + if (divisor == 0) // is there an error? + { + if (&ec == &boost::throws()) // throw on error + throw "oops!"; // whatever exception you prefer + ec = error_code(EDOM, generic_category()); // report error via error_code + return 0; + } + + if (&ec != &boost::throws()) // error reporting via error_code + ec.clear(); + return dividend / divisor; +}+— end Example]
+
@@ -818,7 +822,7 @@ application program interfaces.
Revised
-January 06, 2014
+September 07, 2017
© Copyright Beman Dawes, 2006, 2007, 2008, 2013
diff --git a/test/error_code_test.cpp b/test/error_code_test.cpp
index 3cad994..043f23e 100644
--- a/test/error_code_test.cpp
+++ b/test/error_code_test.cpp
@@ -56,6 +56,50 @@ namespace
ss >> s;
BOOST_TEST( s == expected );
}
+
+ // throws_function_test ------------------------------------------------------------//
+
+ // usage example
+
+ int divide(int dividend, int divisor, boost::system::error_code& ec = boost::throws())
+ {
+ if (divisor == 0) // is there an error?
+ {
+ if (&ec == &boost::throws()) // throw on error
+ throw "oops!"; // whatever exception you prefer
+ ec = error_code(EDOM, generic_category()); // report error via error_code
+ return 0;
+ }
+
+ if (&ec != &boost::throws()) // error reporting via error_code
+ ec.clear();
+ return dividend / divisor;
+ }
+
+ // test usage example
+
+ void test_throws_usage()
+ {
+ std::cout << "Test throws() example and usage...\n";
+ error_code ec;
+
+ // no error tests
+ BOOST_TEST_EQ((divide(10, 2)), 5); // no error, report via exception
+ ec = make_error_code(errc::argument_out_of_domain);
+ BOOST_TEST_EQ((divide(10, 5, ec)), 2); // no error, report via error_code
+ BOOST_TEST(!ec);
+
+ ec = make_error_code(errc::argument_out_of_domain);
+ BOOST_TEST_EQ((divide(10, 0, ec)), 0); // error, report via error_code
+ BOOST_TEST(ec);
+
+ bool exception_thrown = false;
+ try
+ { divide(10, 0); } // error, report via exception
+ catch (...)
+ { exception_thrown = true; }
+ BOOST_TEST(exception_thrown);
+ }
}
// main ------------------------------------------------------------------------------//
@@ -202,6 +246,8 @@ int main( int, char ** )
BOOST_TEST( econd.message() != "" );
BOOST_TEST( econd.message().substr( 0, 13) != "Unknown error" );
+ test_throws_usage();
+
#ifdef BOOST_WINDOWS_API
std::cout << "Windows tests...\n";
// these tests probe the Windows errc decoder
From e039a454cf4fb7cba5d4e1a3409487ceb133a44c Mon Sep 17 00:00:00 2001
From: Beman
Date: Thu, 7 Sep 2017 16:36:48 -0400
Subject: [PATCH 2/3] Hand add the fix from github.com/boostorg/system/pull/12.
Note: This fix was verified by testing in release mode with clang 4.0 on
Linux. It crashed before applying the P/R and passed afterwards. The pull
request was applied by hand to add some new comments and do some other minor
code rearrangements. Thanks to Visigoth for the P/R.
---
include/boost/system/error_code.hpp | 16 +++++++++++++---
test/error_code_test.cpp | 3 +++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp
index 12191f9..080bb27 100644
--- a/include/boost/system/error_code.hpp
+++ b/include/boost/system/error_code.hpp
@@ -542,8 +542,9 @@ namespace boost
// "throws" function in namespace boost rather than namespace boost::system.
} // namespace system
-
- namespace detail { inline system::error_code * throws() { return 0; } }
+
+ namespace detail
+ {
// Misuse of the error_code object is turned into a noisy failure by
// poisoning the reference. This particular implementation doesn't
// produce warnings or errors from popular compilers, is very efficient
@@ -551,8 +552,17 @@ namespace boost
// from order of initialization problems. In practice, it also seems
// cause user function error handling implementation errors to be detected
// very early in the development cycle.
+ inline system::error_code* throws()
+ {
+ // See github.com/boostorg/system/pull/12 by visigoth for why the return
+ // is poisoned with (1) rather than (0). A test, test_throws_usage(), has
+ // been added to error_code_test.cpp, and as visigoth mentioned it fails
+ // on clang for release builds with a return of 0 but works fine with (1).
+ return reinterpret_cast(1);
+ }
+ }
- inline system::error_code & throws()
+ inline system::error_code& throws()
{ return *detail::throws(); }
namespace system
diff --git a/test/error_code_test.cpp b/test/error_code_test.cpp
index 043f23e..baf3853 100644
--- a/test/error_code_test.cpp
+++ b/test/error_code_test.cpp
@@ -99,6 +99,9 @@ namespace
catch (...)
{ exception_thrown = true; }
BOOST_TEST(exception_thrown);
+
+ //error_code should_fail(boost::throws()); // should fail at runtime
+ //boost::throws() = ec; // should fail at runtime
}
}
From cd38d2f77812f99eba86a9533046e6968e897656 Mon Sep 17 00:00:00 2001
From: Beman
Date: Fri, 8 Sep 2017 15:44:52 -0400
Subject: [PATCH 3/3] Remove unused assignment. This was pull request 15, which
was made against master instead of develop.
---
include/boost/system/detail/error_code.ipp | 1 -
1 file changed, 1 deletion(-)
diff --git a/include/boost/system/detail/error_code.ipp b/include/boost/system/detail/error_code.ipp
index 77b191a..dec55d3 100644
--- a/include/boost/system/detail/error_code.ipp
+++ b/include/boost/system/detail/error_code.ipp
@@ -154,7 +154,6 @@ namespace
# endif
if ( sz > sizeof(buf) ) std::free( bp );
- sz = 0;
return msg;
# endif // else POSIX version of strerror_r
# endif // else use strerror_r