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.

operator<<( basic_ostream<charT,traits>& os, const error_code & ec ); size_t hash_value( const error_code & ec ); - } -} + + } // namespace system + + system::error_code & throws(); + +} // namespace boost

The value of each errc_t constant shall be the same as the value of the <cerrno> macro shown in the above synopsis.

@@ -644,36 +647,6 @@ observers 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 object

-
extern error_code throws;
-

The predefined error_code object throws is supplied -for use as a "throw on error" tag.

-

Semantics of throws object

-

Functions 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:

- -

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 from system_error. The - exception's code() member function returns a reference to an - error_code object with the behavior specified in - Postconditions.

-

Non-member functions

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.

+

Function 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]

+
+

Header <boost/system/system_error.hpp>

Class @@ -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