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 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 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 have std::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 throws e.

  • Otherwise, the function throws an object of a type derived from E, derived from boost::exception, if E doesn’t already derive from it, and containing the necessary support for boost::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 have std::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 throws e.

  • Otherwise, the function throws an object of a type derived from E, derived from boost::exception, if E doesn’t already derive from 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.

  • If dynamic_cast<boost::exception const*>( e ) returns a nonzero value, returns the source location stored in that boost::exception subobject, if any.

  • Otherwise, returns a default constructed source location.

This documentation is