mirror of
https://github.com/boostorg/throw_exception.git
synced 2025-07-19 23:32:20 +02:00
Update documentation
This commit is contained in:
287
doc/examples.adoc
Normal file
287
doc/examples.adoc
Normal 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'
|
||||
```
|
Reference in New Issue
Block a user