Description
The header <boost/throw_exception.hpp>
provides a common Boost infrastructure
for throwing exceptions, in the form of a function boost::throw_exception
and a macro BOOST_THROW_EXCEPTION
.
boost::throw_exception(x);
is a replacement for throw x;
that both
degrades gracefully when exception handling support is not available, and
integrates the thrown exception into facilities provided by
Boost.Exception, such as automatically
providing a base class of type boost::exception
and support for
boost::exception_ptr
.
When exception handling is not available, the function is only declared, but not defined. This allows users to provide their own definition.
An overload for boost::throw_exception
that takes a
boost::source_location
is provided. It records the supplied source location into the boost::exception
base class, from where it can later be retrieved when the exception is caught.
boost::diagnostic_information
automatically displays the stored source location.
The macro BOOST_THROW_EXCEPTION(x)
expands to
::boost::throw_exception(x, BOOST_CURRENT_LOCATION)
, passing the current source
location.
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.
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)
.
boost::get_throw_location
also works for exceptions thrown by the two argument
overload of boost::throw_exception
, or by BOOST_THROW_EXCEPTION
; in this case
it returns the source location stored in the boost::exception
base class.
Examples
Using BOOST_THROW_EXCEPTION
Demonstrates the use of BOOST_THROW_EXCEPTION
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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:
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <boost/throw_exception.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/core/verbose_terminate_handler.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()
{
std::set_terminate( boost::core::verbose_terminate_handler );
f1( 0, 3 );
f2( 4, 3 );
}
Sample output:
std::terminate called after throwing an exception:
type: boost::wrapexcept<std::out_of_range>
what(): Index out of range: 4 >= 3
location: <source>:31:34 in function 'f2'
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <boost/throw_exception.hpp>
#include <boost/core/verbose_terminate_handler.hpp>
#include <stdexcept>
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( boost::core::verbose_terminate_handler );
return f1( -4 );
}
Sample output:
std::terminate called after throwing an exception:
type: boost::detail::with_throw_location<std::invalid_argument>
what(): f1: x cannot be negative
location: <source>:9: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 functions such as f2
are typically called from more than one place
in the program, 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <boost/throw_exception.hpp>
#include <boost/core/verbose_terminate_handler.hpp>
#include <stdexcept>
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( boost::core::verbose_terminate_handler );
return f1( 3 ) + f2( -11 );
}
Sample output:
std::terminate called after throwing an exception:
type: boost::detail::with_throw_location<std::invalid_argument>
what(): f2: x cannot be negative
location: <source>:38:22 in function 'main'
Revision History
Changes in 1.79.0
-
Added
boost::throw_with_location
, a more lightweight alternative ofBOOST_THROW_EXCEPTION
for programs that do not use Boost.Exception.
Changes in 1.73.0
-
Added an overload of
throw_exception
that takes aboost::source_location
object.
Note
|
Projects using BOOST_THROW_EXCEPTION with exceptions disabled will need
to add a definition of this new overload.
|
Reference
<boost/throw_exception.hpp> Synopsis
#include <boost/assert/source_location.hpp>
#include <boost/config.hpp>
#include <exception>
namespace boost
{
#if defined( BOOST_NO_EXCEPTIONS )
BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
BOOST_NORETURN void throw_exception( std::exception const & e,
boost::source_location const & loc ); // user defined
#else
template<class E> BOOST_NORETURN void throw_exception( E const & e );
template<class E> BOOST_NORETURN void throw_exception( E const & e,
boost::source_location const & loc );
#endif
} // namespace boost
#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
#if defined( BOOST_NO_EXCEPTIONS )
BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
#else
template<class E> BOOST_NORETURN void throw_exception( E const & e );
#endif
- Requires:
-
E
must havestd::exception
as a public and unambiguous base class. - Effects:
-
-
When exceptions aren’t available, the function is declared, but not defined. The user is expected to supply an appropriate definition.
-
Otherwise, if
BOOST_EXCEPTION_DISABLE
is defined, the function throwse
. -
Otherwise, the function throws an object of a type derived from
E
, derived fromboost::exception
, ifE
doesn’t already derive from it, and containing the necessary support forboost::exception_ptr
.
-
#if defined( BOOST_NO_EXCEPTIONS )
BOOST_NORETURN void throw_exception( std::exception const & e,
boost::source_location const & loc ); // user defined
#else
template<class E> BOOST_NORETURN void throw_exception( E const & e,
boost::source_location const & loc );
#endif
- Requires:
-
E
must havestd::exception
as a public and unambiguous base class. - Effects:
-
-
When exceptions aren’t available, the function is declared, but not defined. The user is expected to supply an appropriate definition.
-
Otherwise, if
BOOST_EXCEPTION_DISABLE
is defined, the function throwse
. -
Otherwise, the function throws an object of a type derived from
E
, derived fromboost::exception
, ifE
doesn’t already derive from it, and containing the necessary support forboost::exception_ptr
. Theboost::exception
base class is initialized to contain the source locationloc
.
-
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 havestd::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 objectx
is caught asstd::exception
orE
,boost::get_throw_location( x )
would returnloc
.
-
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 byboost::throw_with_location( x, loc )
, returnsloc
. -
If
dynamic_cast<boost::exception const*>( e )
returns a nonzero value, returns the source location stored in thatboost::exception
subobject, if any. -
Otherwise, returns a default constructed source location.
-
Appendix A: Copyright and License
This documentation is
-
Copyright 2019, 2022 Peter Dimov
-
Distributed under the Boost Software License, Version 1.0.