Update documentation

This commit is contained in:
Peter Dimov
2022-02-12 03:33:44 +02:00
parent 3e51d32285
commit b3a7f8e178
5 changed files with 343 additions and 83 deletions

View File

@ -1,5 +1,5 @@
////
Copyright 2019 Peter Dimov
Copyright 2019, 2022 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt
////
@ -10,6 +10,11 @@ http://www.boost.org/LICENSE_1_0.txt
:toc-title:
:idprefix:
## Changes in 1.79.0
* Added `boost::throw_with_location`, a more lightweight alternative of
`BOOST_THROW_EXCEPTION` for programs that do not use Boost.Exception.
## Changes in 1.73.0
* Added an overload of `throw_exception` that takes a `boost::source_location`

View File

@ -1,5 +1,5 @@
////
Copyright 2019 Peter Dimov
Copyright 2019, 2022 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt
////
@ -35,83 +35,12 @@ The macro `BOOST_THROW_EXCEPTION(x)` expands to
`::boost::throw_exception(x, BOOST_CURRENT_LOCATION)`, passing the current source
location.
[#examples]
# Examples
:toc:
:toc-title:
:idprefix:
When integration with Boost.Exception and `boost::exception_ptr` is not needed,
the function `boost::throw_with_location` can be used instead. It also throws
a user-provided exception, associating it with a supplied or inferred source
location, but does not supply the `boost::exception` base class and does not
enable `boost::exception_ptr` support.
## Using BOOST_THROW_EXCEPTION
```
#include <boost/throw_exception.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <stdexcept>
#include <iostream>
void f()
{
BOOST_THROW_EXCEPTION( std::runtime_error( "Unspecified runtime error" ) );
}
int main()
{
try
{
f();
}
catch( std::exception const & x )
{
std::cerr << boost::diagnostic_information( x ) << std::endl;
}
}
```
## Using boost::throw_exception with a source location
```
#include <boost/throw_exception.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <stdexcept>
#include <cstddef>
#include <iostream>
void throw_index_error( std::size_t i, std::size_t n,
boost::source_location const & loc )
{
std::string msg = "Index out of range: "
+ boost::lexical_cast<std::string>( i ) + " >= "
+ boost::lexical_cast<std::string>( n );
boost::throw_exception( std::out_of_range( msg ), loc );
}
void f1( std::size_t i, std::size_t n )
{
if( i >= n )
{
throw_index_error( i, n, BOOST_CURRENT_LOCATION );
}
}
void f2( std::size_t i, std::size_t n )
{
if( i >= n )
{
throw_index_error( i, n, BOOST_CURRENT_LOCATION );
}
}
int main()
{
try
{
f1( 4, 3 );
}
catch( std::exception const & x )
{
std::cerr << boost::diagnostic_information( x ) << std::endl;
}
}
```
The source location of the exception thrown by `boost::throw_with_location`
can be retrieved, after `catch(std::exception const & x)`, by using
`boost::get_throw_location(x)`.

287
doc/examples.adoc Normal file
View File

@ -0,0 +1,287 @@
////
Copyright 2019, 2022 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt
////
[#examples]
# Examples
:toc:
:toc-title:
:idprefix:
## Using BOOST_THROW_EXCEPTION
Demonstrates the use of `BOOST_THROW_EXCEPTION`.
```
#include <boost/throw_exception.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <stdexcept>
#include <iostream>
void f()
{
BOOST_THROW_EXCEPTION( std::runtime_error( "Unspecified runtime error" ) );
}
int main()
{
try
{
f();
}
catch( std::exception const & x )
{
std::cerr << boost::diagnostic_information( x ) << std::endl;
}
}
```
Sample output:
```none
example.cpp(8): Throw in function void f()
Dynamic exception type: boost::wrapexcept<std::runtime_error>
std::exception::what: Unspecified runtime error
```
## Using boost::throw_exception with a source location
Demonstrates moving the call to `boost::throw_exception` to a common
helper function that can be marked `BOOST_NOINLINE` to avoid
unnecessary code duplication. The source location is passed
explicitly to the helper function so that it can still record the
logical throw point, instead of always pointing into the helper.
```
#include <boost/throw_exception.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <stdexcept>
#include <cstddef>
#include <iostream>
BOOST_NORETURN BOOST_NOINLINE
void throw_index_error( std::size_t i, std::size_t n,
boost::source_location const & loc )
{
std::string msg = "Index out of range: "
+ boost::lexical_cast<std::string>( i ) + " >= "
+ boost::lexical_cast<std::string>( n );
boost::throw_exception( std::out_of_range( msg ), loc );
}
void f1( std::size_t i, std::size_t n )
{
if( i >= n )
{
throw_index_error( i, n, BOOST_CURRENT_LOCATION );
}
}
void f2( std::size_t i, std::size_t n )
{
if( i >= n )
{
throw_index_error( i, n, BOOST_CURRENT_LOCATION );
}
}
int main()
{
try
{
f1( 0, 3 );
f2( 4, 3 );
}
catch( std::exception const & x )
{
std::cerr << boost::diagnostic_information( x ) << std::endl;
}
}
```
Sample output:
```none
example.cpp(31): Throw in function void f2(std::size_t, std::size_t)
Dynamic exception type: boost::wrapexcept<std::out_of_range>
std::exception::what: Index out of range: 4 >= 3
```
## Using boost::throw_with_location
This example demonstrates a trivial use of `boost::throw_with_location`. Since
a source location is not supplied, the location of the call to
`boost::throw_with_location` is implicitly captured.
```
#include <boost/throw_exception.hpp>
#include <boost/core/demangle.hpp>
#include <stdexcept>
#include <cstdio>
void my_terminate_handler();
int f1( int x )
{
if( x < 0 )
{
boost::throw_with_location(
std::invalid_argument( "f1: x cannot be negative" ) );
}
return x;
}
int main()
{
std::set_terminate( my_terminate_handler );
return f1( -4 );
}
void my_terminate_handler()
{
std::set_terminate( 0 );
try
{
throw;
}
catch( std::exception const& x )
{
boost::source_location loc = boost::get_throw_location( x );
std::string type = boost::core::demangle( typeid( x ).name() );
fprintf( stderr,
"std::terminate called after throwing an exception:\n"
" type: %s\n"
" what(): %s\n"
" location: %s:%u:%u in function '%s'\n",
type.c_str(),
x.what(),
loc.file_name(), (unsigned)loc.line(),
(unsigned)loc.column(), loc.function_name()
);
}
catch( ... )
{
fputs( "std::terminate called after throwing an unknown exception", stderr );
}
std::abort();
}
```
Sample output:
```none
std::terminate called after throwing an exception:
type: boost::detail::with_throw_location<std::invalid_argument>
what(): f1: x cannot be negative
location: <source>:12:9 in function 'f1'
```
## Using boost::throw_with_location with an explicit source location
In this example, the call to `boost::throw_with_location` is moved into
a common helper function. Note how the "API" functions `f1` and `f2`
take a source location argument that defaults to `BOOST_CURRENT_LOCATION`.
This allows the source location attached to the exception to point at
the location of the call to `f2`, rather than inside of `f2`.
Since `f2` is typically called many times, this is usually what we want,
because it enables us to identify the throwing call, rather than merely
to know that it was `f2` that threw.
```
#include <boost/throw_exception.hpp>
#include <boost/core/demangle.hpp>
#include <stdexcept>
#include <cstdio>
void my_terminate_handler();
BOOST_NORETURN BOOST_NOINLINE
void throw_invalid_argument( char const * msg,
boost::source_location const & loc )
{
boost::throw_with_location( std::invalid_argument( msg ), loc );
}
int f1( int x,
boost::source_location const & loc = BOOST_CURRENT_LOCATION )
{
if( x < 0 )
{
throw_invalid_argument( "f1: x cannot be negative", loc );
}
return x;
}
int f2( int x,
boost::source_location const & loc = BOOST_CURRENT_LOCATION )
{
if( x < 0 )
{
throw_invalid_argument( "f2: x cannot be negative", loc );
}
return x;
}
int main()
{
std::set_terminate( my_terminate_handler );
return f1( 3 ) + f2( -11 );
}
void my_terminate_handler()
{
std::set_terminate( 0 );
try
{
throw;
}
catch( std::exception const& x )
{
boost::source_location loc = boost::get_throw_location( x );
std::string type = boost::core::demangle( typeid( x ).name() );
fprintf( stderr,
"std::terminate called after throwing an exception:\n"
" type: %s\n"
" what(): %s\n"
" location: %s:%u:%u in function '%s'\n",
type.c_str(),
x.what(),
loc.file_name(), (unsigned)loc.line(),
(unsigned)loc.column(), loc.function_name()
);
}
catch( ... )
{
fputs( "std::terminate called after throwing an unknown exception",
stderr );
}
std::abort();
}
```
Sample output:
```none
std::terminate called after throwing an exception:
type: boost::detail::with_throw_location<std::invalid_argument>
what(): f2: x cannot be negative
location: <source>:41:22 in function 'main'
```

View File

@ -1,5 +1,5 @@
////
Copyright 2017, 2019 Peter Dimov
Copyright 2017, 2019, 2022 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt
////
@ -15,6 +15,7 @@ Peter Dimov, Emil Dotchevski
:leveloffset: +1
include::description.adoc[]
include::examples.adoc[]
include::changes.adoc[]
include::reference.adoc[]
@ -25,5 +26,5 @@ include::reference.adoc[]
This documentation is
* Copyright 2019 Peter Dimov
* Copyright 2019, 2022 Peter Dimov
* Distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].

View File

@ -41,6 +41,16 @@ template<class E> BOOST_NORETURN void throw_exception( E const & e,
#define BOOST_THROW_EXCEPTION(x) \
::boost::throw_exception(x, BOOST_CURRENT_LOCATION)
namespace boost
{
template<class E> BOOST_NORETURN void throw_with_location( E && e,
boost::source_location const & loc = BOOST_CURRENT_LOCATION );
template<class E> boost::source_location get_throw_location( E const & e );
} // namespace boost
```
## throw_exception
@ -96,3 +106,31 @@ Effects: ::
it, and containing the necessary support for `boost::exception_ptr`. The
`boost::exception` base class is initialized to contain the source
location `loc`.
## throw_with_location
```
template<class E> BOOST_NORETURN void throw_with_location( E && e,
boost::source_location const & loc = BOOST_CURRENT_LOCATION );
```
Requires: :: `std::decay<E>::type` must have `std::exception` as a public
and unambiguous base class.
Effects: ::
* When exceptions aren't available, `boost::throw_exception( e, loc );`
* Otherwise, the function throws an object of a type derived from `E`,
such that, if this object `x` is caught as `std::exception` or `E`,
`boost::get_throw_location( x )` would return `loc`.
## get_throw_location
```
template<class E> boost::source_location get_throw_location( E const & e );
```
Requires: :: `E` must be polymorphic.
Effects: :: If `e` is a subobject of the object thrown by
`boost::throw_with_location( x, loc )`, returns `loc`. Otherwise, returns
a default constructed source location.