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:
@ -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`
|
||||
|
@ -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
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'
|
||||
```
|
@ -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].
|
||||
|
@ -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.
|
||||
|
||||
|
Reference in New Issue
Block a user