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