Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / hana / flatten.hpp
1 /*!
2 @file
3 Defines `boost::hana::flatten`.
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_FLATTEN_HPP
11 #define BOOST_HANA_FLATTEN_HPP
12
13 #include <boost/hana/fwd/flatten.hpp>
14
15 #include <boost/hana/concept/monad.hpp>
16 #include <boost/hana/concept/sequence.hpp>
17 #include <boost/hana/config.hpp>
18 #include <boost/hana/core/dispatch.hpp>
19 #include <boost/hana/core/make.hpp>
20 #include <boost/hana/detail/unpack_flatten.hpp>
21 #include <boost/hana/functional/id.hpp>
22 #include <boost/hana/fwd/chain.hpp>
23
24 #include <cstddef>
25 #include <utility>
26
27
28 BOOST_HANA_NAMESPACE_BEGIN
29     //! @cond
30     template <typename Xs>
31     constexpr auto flatten_t::operator()(Xs&& xs) const {
32         using M = typename hana::tag_of<Xs>::type;
33         using Flatten = BOOST_HANA_DISPATCH_IF(flatten_impl<M>,
34             hana::Monad<M>::value
35         );
36
37 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
38         static_assert(hana::Monad<M>::value,
39         "hana::flatten(xs) requires 'xs' to be a Monad");
40 #endif
41
42         return Flatten::apply(static_cast<Xs&&>(xs));
43     }
44     //! @endcond
45
46     template <typename M, bool condition>
47     struct flatten_impl<M, when<condition>> : default_ {
48         template <typename Xs>
49         static constexpr auto apply(Xs&& xs)
50         { return hana::chain(static_cast<Xs&&>(xs), hana::id); }
51     };
52
53     template <typename S>
54     struct flatten_impl<S, when<Sequence<S>::value>> {
55         template <typename Xs>
56         static constexpr auto apply(Xs&& xs) {
57             return detail::unpack_flatten(static_cast<Xs&&>(xs), hana::make<S>);
58         }
59     };
60 BOOST_HANA_NAMESPACE_END
61
62 #endif // !BOOST_HANA_FLATTEN_HPP