2
0
mirror of https://github.com/boostorg/leaf.git synced 2026-01-19 04:22:08 +00:00

faster to compile tuple handlers implementation

This commit is contained in:
Emil Dotchevski
2020-06-14 10:51:26 -07:00
parent e42b845ff1
commit 08b43478c4
6 changed files with 92 additions and 183 deletions

9
.vscode/tasks.json vendored
View File

@@ -311,15 +311,6 @@
"command": "${workspaceRoot}/.vscode/msvc.bat && cd ${workspaceRoot}/bld/debug && meson test exception_to_result_test"
}
},
{
"label": "flatten_tuple_test",
"type": "shell",
"command": "cd ${workspaceRoot}/bld/debug && meson test flatten_tuple_test",
"problemMatcher": { "base": "$gcc", "fileLocation": ["relative","${workspaceRoot}/bld/debug"] },
"windows": {
"command": "${workspaceRoot}/.vscode/msvc.bat && cd ${workspaceRoot}/bld/debug && meson test flatten_tuple_test"
}
},
{
"label": "function_traits_test",
"type": "shell",

View File

@@ -3589,66 +3589,68 @@ namespace boost { namespace leaf {
}
};
template <class R, class Tup, class F>
LEAF_CONSTEXPR inline R handle_error_using_handlers_list_( Tup & e_objects, error_info const & ei, F && f )
template <class T>
struct is_tuple: std::false_type { };
template <class T>
struct is_tuple<T &>: is_tuple<T> { };
template <class... T>
struct is_tuple<std::tuple<T...>>: std::true_type { };
template <class R, class Tup, class H>
LEAF_CONSTEXPR inline typename std::enable_if<!is_tuple<H>::value, R>::type handle_error_( Tup & tup, error_info const & ei, H && h )
{
static_assert( handler_matches_any_error<fn_mp_args<F>>::value, "The last handler passed to handle_all must match any error." );
return handler_caller<R, F>::call( e_objects, ei, std::forward<F>(f), fn_mp_args<F>{ } );
static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
}
template <class R, class Tup, class CarF, class... CdrF>
LEAF_CONSTEXPR inline R handle_error_using_handlers_list_( Tup & e_objects, error_info const & ei, CarF && car_f, CdrF && ... cdr_f )
template <class R, class Tup, class H>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<H>::value, R>::type handle_error_( Tup &, error_info const &, H && );
template <class R, class Tup, class Car, class... Cdr>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<Car>::value, R>::type handle_error_( Tup &, error_info const &, Car &&, Cdr && ... );
template <class R, class Tup, class Car, class... Cdr>
LEAF_CONSTEXPR inline typename std::enable_if<!is_tuple<Car>::value, R>::type handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
{
if( handler_matches_any_error<fn_mp_args<CarF>>::value || check_handler_( e_objects, ei, fn_mp_args<CarF>{ } ) )
return handler_caller<R, CarF>::call( e_objects, ei, std::forward<CarF>(car_f), fn_mp_args<CarF>{ } );
if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
else
return handle_error_using_handlers_list_<R>( e_objects, ei, std::forward<CdrF>(cdr_f)...);
return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
}
template <class R, class Tup, class HandlersTuple, size_t ... I>
LEAF_CONSTEXPR inline R handle_error_using_handlers_tuple_helper_( Tup & e_objects, error_info const & ei, HandlersTuple && handlers, leaf_detail_mp11::index_sequence<I...>)
template <class R, class Tup, class HTup, size_t ... I>
LEAF_CONSTEXPR inline R handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
{
return handle_error_using_handlers_list_<R>(e_objects, ei, std::get<I>(std::forward<HandlersTuple>(handlers))...);
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
}
template <class R, class Tup, class... H>
LEAF_CONSTEXPR inline R handle_error_using_handlers_tuple_( Tup & e_objects, error_info const & ei, std::tuple<H...> && handlers )
template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
LEAF_CONSTEXPR inline R handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
{
return handle_error_using_handlers_tuple_helper_<R>(
e_objects,
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
}
template <class R, class Tup, class H>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<H>::value, R>::type handle_error_( Tup & tup, error_info const & ei, H && h )
{
return handle_error_tuple_<R>(
tup,
ei,
std::forward<std::tuple<H...>>(handlers),
leaf_detail_mp11::make_index_sequence<sizeof...(H)>());
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
std::forward<H>(h));
}
template <class T> struct is_tuple: std::false_type { };
template <class... T> struct is_tuple<std::tuple<T...>>: std::true_type { };
template <class H>
constexpr std::tuple<H> inline tuplefy( H h ) noexcept
template <class R, class Tup, class Car, class... Cdr>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<Car>::value, R>::type handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
{
return std::make_tuple(h);
}
template <class... H>
constexpr std::tuple<H...> inline tuplefy( std::tuple<H...> h ) noexcept
{
return h;
}
template <class... H>
constexpr decltype(std::tuple_cat(tuplefy(std::declval<typename std::decay<H>::type>())...)) flatten_tuple( H && ... h ) noexcept
{
return std::tuple_cat(tuplefy(std::forward<H>(h))...);
}
template <class R, class Tup, class... H>
LEAF_CONSTEXPR inline R handle_error_( Tup & e_objects, error_info const & ei, H && ... h )
{
return handle_error_using_handlers_tuple_<R>(
e_objects,
return handle_error_tuple_<R>(
tup,
ei,
flatten_tuple(std::forward<H>(h)...));
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
std::forward<Car>(car),
std::forward<Cdr>(cdr)...);
}
}

View File

@@ -663,66 +663,68 @@ namespace boost { namespace leaf {
}
};
template <class R, class Tup, class F>
LEAF_CONSTEXPR inline R handle_error_using_handlers_list_( Tup & e_objects, error_info const & ei, F && f )
template <class T>
struct is_tuple: std::false_type { };
template <class T>
struct is_tuple<T &>: is_tuple<T> { };
template <class... T>
struct is_tuple<std::tuple<T...>>: std::true_type { };
template <class R, class Tup, class H>
LEAF_CONSTEXPR inline typename std::enable_if<!is_tuple<H>::value, R>::type handle_error_( Tup & tup, error_info const & ei, H && h )
{
static_assert( handler_matches_any_error<fn_mp_args<F>>::value, "The last handler passed to handle_all must match any error." );
return handler_caller<R, F>::call( e_objects, ei, std::forward<F>(f), fn_mp_args<F>{ } );
static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
}
template <class R, class Tup, class CarF, class... CdrF>
LEAF_CONSTEXPR inline R handle_error_using_handlers_list_( Tup & e_objects, error_info const & ei, CarF && car_f, CdrF && ... cdr_f )
template <class R, class Tup, class H>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<H>::value, R>::type handle_error_( Tup &, error_info const &, H && );
template <class R, class Tup, class Car, class... Cdr>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<Car>::value, R>::type handle_error_( Tup &, error_info const &, Car &&, Cdr && ... );
template <class R, class Tup, class Car, class... Cdr>
LEAF_CONSTEXPR inline typename std::enable_if<!is_tuple<Car>::value, R>::type handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
{
if( handler_matches_any_error<fn_mp_args<CarF>>::value || check_handler_( e_objects, ei, fn_mp_args<CarF>{ } ) )
return handler_caller<R, CarF>::call( e_objects, ei, std::forward<CarF>(car_f), fn_mp_args<CarF>{ } );
if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
else
return handle_error_using_handlers_list_<R>( e_objects, ei, std::forward<CdrF>(cdr_f)...);
return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
}
template <class R, class Tup, class HandlersTuple, size_t ... I>
LEAF_CONSTEXPR inline R handle_error_using_handlers_tuple_helper_( Tup & e_objects, error_info const & ei, HandlersTuple && handlers, leaf_detail_mp11::index_sequence<I...>)
template <class R, class Tup, class HTup, size_t ... I>
LEAF_CONSTEXPR inline R handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
{
return handle_error_using_handlers_list_<R>(e_objects, ei, std::get<I>(std::forward<HandlersTuple>(handlers))...);
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
}
template <class R, class Tup, class... H>
LEAF_CONSTEXPR inline R handle_error_using_handlers_tuple_( Tup & e_objects, error_info const & ei, std::tuple<H...> && handlers )
template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
LEAF_CONSTEXPR inline R handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
{
return handle_error_using_handlers_tuple_helper_<R>(
e_objects,
return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
}
template <class R, class Tup, class H>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<H>::value, R>::type handle_error_( Tup & tup, error_info const & ei, H && h )
{
return handle_error_tuple_<R>(
tup,
ei,
std::forward<std::tuple<H...>>(handlers),
leaf_detail_mp11::make_index_sequence<sizeof...(H)>());
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
std::forward<H>(h));
}
template <class T> struct is_tuple: std::false_type { };
template <class... T> struct is_tuple<std::tuple<T...>>: std::true_type { };
template <class H>
constexpr std::tuple<H> inline tuplefy( H h ) noexcept
template <class R, class Tup, class Car, class... Cdr>
LEAF_CONSTEXPR inline typename std::enable_if<is_tuple<Car>::value, R>::type handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
{
return std::make_tuple(h);
}
template <class... H>
constexpr std::tuple<H...> inline tuplefy( std::tuple<H...> h ) noexcept
{
return h;
}
template <class... H>
constexpr decltype(std::tuple_cat(tuplefy(std::declval<typename std::decay<H>::type>())...)) flatten_tuple( H && ... h ) noexcept
{
return std::tuple_cat(tuplefy(std::forward<H>(h))...);
}
template <class R, class Tup, class... H>
LEAF_CONSTEXPR inline R handle_error_( Tup & e_objects, error_info const & ei, H && ... h )
{
return handle_error_using_handlers_tuple_<R>(
e_objects,
return handle_error_tuple_<R>(
tup,
ei,
flatten_tuple(std::forward<H>(h)...));
leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
std::forward<Car>(car),
std::forward<Cdr>(cdr)...);
}
}

View File

@@ -106,7 +106,6 @@ tests = [
'error_id_test',
'exception_test',
'exception_to_result_test',
'flatten_tuple_test',
'function_traits_test',
'handle_all_other_result_test',
'handle_all_test',

View File

@@ -61,7 +61,6 @@ run error_code_test.cpp ;
run error_id_test.cpp ;
run exception_test.cpp ;
run exception_to_result_test.cpp ;
run flatten_tuple_test.cpp ;
run function_traits_test.cpp ;
run handle_all_other_result_test.cpp ;
run handle_all_test.cpp ;

View File

@@ -1,84 +0,0 @@
// Copyright (c) 2018-2020 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/handle_error.hpp>
#include "lightweight_test.hpp"
using boost::leaf::leaf_detail::flatten_tuple;
static_assert(std::is_same<
decltype(flatten_tuple(int{}, float{})),
std::tuple<int, float>>
::value, "flatten_tuple_failure");
static_assert(std::is_same<
decltype(flatten_tuple(std::tuple<int,float>{}, std::tuple<short,long>{})),
std::tuple<int, float, short, long>>
::value, "flatten_tuple_failure");
static_assert(std::is_same<
decltype(flatten_tuple(std::tuple<int,float>{}, short{}, long{})),
std::tuple<int, float, short, long>>
::value, "flatten_tuple_failure");
static_assert(std::is_same<
decltype(flatten_tuple(int{}, std::tuple<float, short>{}, long{})),
std::tuple<int, float, short, long>>
::value, "flatten_tuple_failure");
int main()
{
BOOST_TEST(
flatten_tuple(int{1}, float{2}, std::make_tuple(short{3},long{4}))
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
BOOST_TEST(
flatten_tuple(std::make_tuple(int{1}, float{2}), std::make_tuple(short{3},long{4}))
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
BOOST_TEST(
flatten_tuple(std::make_tuple(int{1}, float{2}), short{3}, long{4})
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
BOOST_TEST(
flatten_tuple(int{1}, std::make_tuple(float{2}, short{3}), long{4})
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
{
int i = 1;
float f = 2;
auto t = std::make_tuple(short{3},long{4});
BOOST_TEST(
flatten_tuple(i, f, t)
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
}
{
int const i = 1;
float const f = 2;
auto const t = std::make_tuple(short{3},long{4});
BOOST_TEST(
flatten_tuple(i, f, t)
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
}
{
int const & i = 1;
float const & f = 2;
auto const & t = std::make_tuple(short{3},long{4});
BOOST_TEST(
flatten_tuple(i, f, t)
==
std::make_tuple(int{1}, float{2}, short{3}, long{4}));
}
return boost::report_errors();
}