concat.hpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*!
  2. @file
  3. Defines `boost::hana::concat`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_CONCAT_HPP
  9. #define BOOST_HANA_CONCAT_HPP
  10. #include <boost/hana/fwd/concat.hpp>
  11. #include <boost/hana/at.hpp>
  12. #include <boost/hana/concept/monad_plus.hpp>
  13. #include <boost/hana/concept/sequence.hpp>
  14. #include <boost/hana/config.hpp>
  15. #include <boost/hana/core/dispatch.hpp>
  16. #include <boost/hana/core/make.hpp>
  17. #include <boost/hana/length.hpp>
  18. #include <cstddef>
  19. #include <type_traits>
  20. #include <utility>
  21. BOOST_HANA_NAMESPACE_BEGIN
  22. //! @cond
  23. template <typename Xs, typename Ys>
  24. constexpr auto concat_t::operator()(Xs&& xs, Ys&& ys) const {
  25. using M = typename hana::tag_of<Xs>::type;
  26. using Concat = BOOST_HANA_DISPATCH_IF(concat_impl<M>,
  27. hana::MonadPlus<M>::value &&
  28. std::is_same<typename hana::tag_of<Ys>::type, M>::value
  29. );
  30. #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
  31. static_assert(std::is_same<typename hana::tag_of<Ys>::type, M>::value,
  32. "hana::concat(xs, ys) requires 'xs' and 'ys' to have the same tag");
  33. static_assert(hana::MonadPlus<M>::value,
  34. "hana::concat(xs, ys) requires 'xs' and 'ys' to be MonadPlus");
  35. #endif
  36. return Concat::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
  37. }
  38. //! @endcond
  39. template <typename M, bool condition>
  40. struct concat_impl<M, when<condition>> : default_ {
  41. template <typename ...Args>
  42. static constexpr auto apply(Args&& ...) = delete;
  43. };
  44. template <typename S>
  45. struct concat_impl<S, when<Sequence<S>::value>> {
  46. template <typename Xs, typename Ys, std::size_t ...xi, std::size_t ...yi>
  47. static constexpr auto
  48. concat_helper(Xs&& xs, Ys&& ys, std::index_sequence<xi...>,
  49. std::index_sequence<yi...>)
  50. {
  51. return hana::make<S>(
  52. hana::at_c<xi>(static_cast<Xs&&>(xs))...,
  53. hana::at_c<yi>(static_cast<Ys&&>(ys))...
  54. );
  55. }
  56. template <typename Xs, typename Ys>
  57. static constexpr auto apply(Xs&& xs, Ys&& ys) {
  58. constexpr std::size_t xi = decltype(hana::length(xs))::value;
  59. constexpr std::size_t yi = decltype(hana::length(ys))::value;
  60. return concat_helper(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys),
  61. std::make_index_sequence<xi>{},
  62. std::make_index_sequence<yi>{});
  63. }
  64. };
  65. BOOST_HANA_NAMESPACE_END
  66. #endif // !BOOST_HANA_CONCAT_HPP