Skip to content

Commit

Permalink
Issue #33
Browse files Browse the repository at this point in the history
  • Loading branch information
zajo committed Nov 21, 2021
1 parent a24b2b0 commit 35295d2
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 7 deletions.
21 changes: 14 additions & 7 deletions include/boost/leaf/exception.hpp
Expand Up @@ -86,6 +86,13 @@ namespace leaf_detail
exception( exception const & ) = default;
exception( exception && ) = default;

BOOST_LEAF_CONSTEXPR exception( error_id id, Ex const & ex ) noexcept:
Ex(ex),
error_id(id)
{
enforce_std_exception(*this);
}

BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept:
Ex(std::move(ex)),
error_id(id)
Expand All @@ -109,22 +116,22 @@ namespace leaf_detail
template <class T, class... Rest>
struct at_least_one_derives_from_std_exception<T, Rest...>
{
constexpr static const bool value = std::is_base_of<std::exception,T>::value || at_least_one_derives_from_std_exception<Rest...>::value;
constexpr static const bool value = std::is_base_of<std::exception,typename std::remove_reference<T>::type>::value || at_least_one_derives_from_std_exception<Rest...>::value;
};
}

template <class Ex, class... E>
inline
typename std::enable_if<std::is_base_of<std::exception,Ex>::value, leaf_detail::exception<Ex>>::type
typename std::enable_if<std::is_base_of<std::exception,typename std::remove_reference<Ex>::type>::value, leaf_detail::exception<typename std::remove_reference<Ex>::type>>::type
exception( error_id err, Ex && ex, E && ... e ) noexcept
{
static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
return leaf_detail::exception<Ex>( err.load(std::forward<E>(e)...), std::forward<Ex>(ex) );
return leaf_detail::exception<typename std::remove_reference<Ex>::type>( err.load(std::forward<E>(e)...), std::forward<Ex>(ex) );
}

template <class E1, class... E>
inline
typename std::enable_if<!std::is_base_of<std::exception,E1>::value, leaf_detail::exception<std::exception>>::type
typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, leaf_detail::exception<std::exception>>::type
exception( error_id err, E1 && car, E && ... cdr ) noexcept
{
static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
Expand All @@ -138,16 +145,16 @@ inline leaf_detail::exception<std::exception> exception( error_id err ) noexcept

template <class Ex, class... E>
inline
typename std::enable_if<std::is_base_of<std::exception,Ex>::value, leaf_detail::exception<Ex>>::type
typename std::enable_if<std::is_base_of<std::exception,typename std::remove_reference<Ex>::type>::value, leaf_detail::exception<typename std::remove_reference<Ex>::type>>::type
exception( Ex && ex, E && ... e ) noexcept
{
static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
return leaf_detail::exception<Ex>( new_error().load(std::forward<E>(e)...), std::forward<Ex>(ex) );
return leaf_detail::exception<typename std::remove_reference<Ex>::type>( new_error().load(std::forward<E>(e)...), std::forward<Ex>(ex) );
}

template <class E1, class... E>
inline
typename std::enable_if<!std::is_base_of<std::exception,E1>::value, leaf_detail::exception<std::exception>>::type
typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, leaf_detail::exception<std::exception>>::type
exception( E1 && car, E && ... cdr ) noexcept
{
static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
Expand Down
2 changes: 2 additions & 0 deletions test/Jamfile.v2
Expand Up @@ -115,6 +115,8 @@ compile-fail _compile-fail-BOOST_LEAF_ASSIGN.cpp ;
compile-fail _compile-fail-BOOST_LEAF_AUTO.cpp ;
compile-fail _compile-fail-diagnostic_info.cpp ;
compile-fail _compile-fail-error_info.cpp ;
compile-fail _compile-fail-exception_1.cpp ;
compile-fail _compile-fail-exception_2.cpp ;
compile-fail _compile-fail-new_error.cpp ;
compile-fail _compile-fail-result_1.cpp ;
compile-fail _compile-fail-result_2.cpp ;
Expand Down
12 changes: 12 additions & 0 deletions test/_compile-fail-exception_1.cpp
@@ -0,0 +1,12 @@
// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.

// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/leaf/exception.hpp>

namespace leaf = boost::leaf;

struct test: std::exception { };

auto e = leaf::exception(std::exception(), test());
12 changes: 12 additions & 0 deletions test/_compile-fail-exception_2.cpp
@@ -0,0 +1,12 @@
// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.

// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/leaf/exception.hpp>

namespace leaf = boost::leaf;

struct test: std::exception { };

auto e = leaf::exception(42, test());
28 changes: 28 additions & 0 deletions test/exception_test.cpp
Expand Up @@ -100,62 +100,90 @@ int main()
BOOST_TEST_EQ(20, test<leaf::catch_<my_exception>>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(20, test<leaf::catch_<my_exception>>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<leaf::catch_<my_exception>>([]{ throw leaf::exception(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<leaf::catch_<my_exception>>([]{ my_exception exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(21, test<leaf::catch_<my_exception>>([]{ my_exception const exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(22, test<leaf::catch_<my_exception>>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(22, test<leaf::catch_<my_exception>>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(23, test<leaf::catch_<my_exception>>([]{ throw leaf::exception(my_exception(42)); }));
BOOST_TEST_EQ(23, test<leaf::catch_<my_exception>>([]{ my_exception exc(42); throw leaf::exception(exc); }));
BOOST_TEST_EQ(23, test<leaf::catch_<my_exception>>([]{ my_exception const exc(42); throw leaf::exception(exc); }));

BOOST_TEST_EQ(20, test<my_exception const &>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(20, test<my_exception const &>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const &>([]{ throw leaf::exception(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const &>([]{ my_exception exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const &>([]{ my_exception const exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(22, test<my_exception const &>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(22, test<my_exception const &>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const &>([]{ throw leaf::exception(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const &>([]{ my_exception exc(42); throw leaf::exception(exc); }));
BOOST_TEST_EQ(23, test<my_exception const &>([]{ my_exception const exc(42); throw leaf::exception(exc); }));

BOOST_TEST_EQ(40, test<my_exception &>([]{ BOOST_LEAF_THROW_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(40, test<my_exception &>([]{ throw BOOST_LEAF_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception &>([]{ throw leaf::exception(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception &>([]{ info inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(41, test<my_exception &>([]{ info const inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(42, test<my_exception &>([]{ BOOST_LEAF_THROW_EXCEPTION(); }));
BOOST_TEST_EQ(42, test<my_exception &>([]{ throw BOOST_LEAF_EXCEPTION(); }));
BOOST_TEST_EQ(43, test<my_exception &>([]{ throw leaf::exception(); }));

BOOST_TEST_EQ(20, test<my_exception const &>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(20, test<my_exception const &>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const &>([]{ throw leaf::exception(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const &>([]{ my_exception exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const &>([]{ my_exception const exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(22, test<my_exception const &>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(22, test<my_exception const &>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const &>([]{ throw leaf::exception(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const &>([]{ my_exception exc(42); throw leaf::exception(exc); }));
BOOST_TEST_EQ(23, test<my_exception const &>([]{ my_exception const exc(42); throw leaf::exception(exc); }));

BOOST_TEST_EQ(40, test<my_exception &>([]{ BOOST_LEAF_THROW_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(40, test<my_exception &>([]{ throw BOOST_LEAF_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception &>([]{ throw leaf::exception(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception &>([]{ info inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(41, test<my_exception &>([]{ info const inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(42, test<my_exception &>([]{ BOOST_LEAF_THROW_EXCEPTION(); }));
BOOST_TEST_EQ(42, test<my_exception &>([]{ throw BOOST_LEAF_EXCEPTION(); }));
BOOST_TEST_EQ(43, test<my_exception &>([]{ throw leaf::exception(); }));

BOOST_TEST_EQ(20, test<my_exception const>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(20, test<my_exception const>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const>([]{ throw leaf::exception(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const>([]{ my_exception exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const>([]{ my_exception const exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(22, test<my_exception const>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(22, test<my_exception const>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const>([]{ throw leaf::exception(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const>([]{ my_exception exc(42); throw leaf::exception(exc); }));
BOOST_TEST_EQ(23, test<my_exception const>([]{ my_exception const exc(42); throw leaf::exception(exc); }));

BOOST_TEST_EQ(40, test<my_exception>([]{ BOOST_LEAF_THROW_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(40, test<my_exception>([]{ throw BOOST_LEAF_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception>([]{ throw leaf::exception(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception>([]{ info inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(41, test<my_exception>([]{ info const inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(42, test<my_exception>([]{ BOOST_LEAF_THROW_EXCEPTION(); }));
BOOST_TEST_EQ(42, test<my_exception>([]{ throw BOOST_LEAF_EXCEPTION(); }));
BOOST_TEST_EQ(43, test<my_exception>([]{ throw leaf::exception(); }));

BOOST_TEST_EQ(20, test<my_exception const>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(20, test<my_exception const>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const>([]{ throw leaf::exception(my_exception(42), info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const>([]{ my_exception exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(21, test<my_exception const>([]{ my_exception const exc(42); throw leaf::exception(exc, info{42}); }));
BOOST_TEST_EQ(22, test<my_exception const>([]{ BOOST_LEAF_THROW_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(22, test<my_exception const>([]{ throw BOOST_LEAF_EXCEPTION(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const>([]{ throw leaf::exception(my_exception(42)); }));
BOOST_TEST_EQ(23, test<my_exception const>([]{ my_exception exc(42); throw leaf::exception(exc); }));
BOOST_TEST_EQ(23, test<my_exception const>([]{ my_exception const exc(42); throw leaf::exception(exc); }));

BOOST_TEST_EQ(40, test<my_exception>([]{ BOOST_LEAF_THROW_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(40, test<my_exception>([]{ throw BOOST_LEAF_EXCEPTION(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception>([]{ throw leaf::exception(info{42}); }));
BOOST_TEST_EQ(41, test<my_exception>([]{ info inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(41, test<my_exception>([]{ info const inf{42}; throw leaf::exception(inf); }));
BOOST_TEST_EQ(42, test<my_exception>([]{ BOOST_LEAF_THROW_EXCEPTION(); }));
BOOST_TEST_EQ(42, test<my_exception>([]{ throw BOOST_LEAF_EXCEPTION(); }));
BOOST_TEST_EQ(43, test<my_exception>([]{ throw leaf::exception(); }));
Expand Down

0 comments on commit 35295d2

Please sign in to comment.