diff --git a/doc/reference.html b/doc/reference.html
index 5671435..8111be9 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -60,8 +60,7 @@
Class 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/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 3cad994..baf3853 100644
--- a/test/error_code_test.cpp
+++ b/test/error_code_test.cpp
@@ -56,6 +56,53 @@ 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);
+
+ //error_code should_fail(boost::throws()); // should fail at runtime
+ //boost::throws() = ec; // should fail at runtime
+ }
}
// main ------------------------------------------------------------------------------//
@@ -202,6 +249,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