From 1bb5b95ebd27de49dc50980d0ac742ce1461563c Mon Sep 17 00:00:00 2001 From: Beman Date: Thu, 7 Sep 2017 15:00:26 -0400 Subject: [PATCH] Rewrite the boost::throws() reference documentation. Add tests of boost::throws() using the divide() function from the reference documentation. Having tests will allow us to change the implementation of throws() without fear of silently breaking it. --- doc/reference.html | 74 +++++++++++++++++++++------------------- test/error_code_test.cpp | 46 +++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 35 deletions(-) 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:

-
    -
  • ec.value() returns the implementation specific error - number for the particular error that occurred.
  • -
  • ec.category() returns the - error_category for ec.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 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/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