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

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'
```