From eda7ea303a0957f901cb02006891cfc8c35ea281 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 26 May 2014 14:21:29 -0400 Subject: [PATCH] Add a more efficient at_index algorithm. --- include/boost/hana/detail/at_index/best.hpp | 22 ++++++++++++ .../detail/at_index/overload_resolution.hpp | 36 +++++++++++++++++++ include/boost/hana/list.hpp | 8 +++++ test/CMakeLists.txt | 1 + test/detail/at_index.cpp | 33 +++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 include/boost/hana/detail/at_index/best.hpp create mode 100644 include/boost/hana/detail/at_index/overload_resolution.hpp create mode 100644 test/detail/at_index.cpp diff --git a/include/boost/hana/detail/at_index/best.hpp b/include/boost/hana/detail/at_index/best.hpp new file mode 100644 index 000000000..97da4572c --- /dev/null +++ b/include/boost/hana/detail/at_index/best.hpp @@ -0,0 +1,22 @@ +/*! + * @file + * Defines `boost::hana::detail::at_index::best`. + * + * + * @copyright Louis Dionne 2014 + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE.md or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_HANA_DETAIL_AT_INDEX_BEST_HPP +#define BOOST_HANA_DETAIL_AT_INDEX_BEST_HPP + +#include + + +namespace boost { namespace hana { namespace detail { namespace at_index { + BOOST_HANA_CONSTEXPR_LAMBDA auto best = overload_resolution; +}}}} + +#endif // !BOOST_HANA_DETAIL_AT_INDEX_BEST_HPP diff --git a/include/boost/hana/detail/at_index/overload_resolution.hpp b/include/boost/hana/detail/at_index/overload_resolution.hpp new file mode 100644 index 000000000..5ed06202b --- /dev/null +++ b/include/boost/hana/detail/at_index/overload_resolution.hpp @@ -0,0 +1,36 @@ +/*! + * @file + * Defines `boost::hana::detail::at_index::overload_resolution`. + * + * + * @copyright Louis Dionne 2014 + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE.md or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_HANA_DETAIL_AT_INDEX_OVERLOAD_RESOLUTION_HPP +#define BOOST_HANA_DETAIL_AT_INDEX_OVERLOAD_RESOLUTION_HPP + +#include +#include + +#include + + +namespace boost { namespace hana { namespace detail { namespace at_index { + struct eat_pod { eat_pod(...) { } }; + + template + constexpr auto overload_impl(index_sequence) { + return [](decltype(ignore, eat_pod{})..., auto nth, ...) { + return nth; + }; + } + + BOOST_HANA_CONSTEXPR_LAMBDA auto overload_resolution = [](auto n, auto ...xs) { + return overload_impl(make_index_sequence{})(xs...); + }; +}}}} // end namespace boost::hana::detail::at_index + +#endif // !BOOST_HANA_DETAIL_AT_INDEX_OVERLOAD_RESOLUTION_HPP diff --git a/include/boost/hana/list.hpp b/include/boost/hana/list.hpp index fb6f86e81..e309963dc 100644 --- a/include/boost/hana/list.hpp +++ b/include/boost/hana/list.hpp @@ -13,6 +13,7 @@ #define BOOST_HANA_LIST_HPP #include +#include #include #include #include @@ -68,6 +69,13 @@ namespace boost { namespace hana { return size_t; }); } + + template + static constexpr auto at_impl(Index n, List xs) { + return xs.into([=](auto ...xs) { + return detail::at_index::best(n, xs...); + }); + } }; template diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dc6b1f1da..0202f9708 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,6 +19,7 @@ boost_hana_add_test(adapted.std_integer_sequence.iterable) boost_hana_add_test(adapted.std_tuple.functor) boost_hana_add_test(adapted.std_tuple.iterable) +boost_hana_add_test(detail.at_index) boost_hana_add_test(detail.comparable_from_iterable) boost_hana_add_test(detail.foldable_from_iterable) boost_hana_add_test(detail.integer_sequence) diff --git a/test/detail/at_index.cpp b/test/detail/at_index.cpp new file mode 100644 index 000000000..ebf835eef --- /dev/null +++ b/test/detail/at_index.cpp @@ -0,0 +1,33 @@ +/* + * Copyright Louis Dionne 2014 + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE.md or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include + +#include +#include +using namespace boost::hana; + + +template +constexpr void test_at(At at) { + BOOST_HANA_STATIC_ASSERT(at(size_t<0>, int_<0>) == int_<0>); + BOOST_HANA_STATIC_ASSERT(at(size_t<0>, int_<0>, int_<1>) == int_<0>); + BOOST_HANA_STATIC_ASSERT(at(size_t<0>, int_<0>, int_<1>, int_<2>) == int_<0>); + + BOOST_HANA_STATIC_ASSERT(at(size_t<1>, int_<0>, int_<1>) == int_<1>); + BOOST_HANA_STATIC_ASSERT(at(size_t<1>, int_<0>, int_<1>, int_<2>) == int_<1>); + + BOOST_HANA_STATIC_ASSERT(at(size_t<2>, int_<0>, int_<1>, int_<2>) == int_<2>); + + BOOST_HANA_STATIC_ASSERT(at(size_t<0>, 0) == 0); + BOOST_HANA_STATIC_ASSERT(at(size_t<1>, 0, '1') == '1'); + BOOST_HANA_STATIC_ASSERT(at(size_t<2>, 0, '1', "2") == "2"); +} + +int main() { + test_at(detail::at_index::overload_resolution); +}