summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/test/_include/support/seq.hpp
blob: ee222dc01d438ae699b3bc1ca52ff956c96962d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#ifndef TEST_SUPPORT_SEQ_HPP
#define TEST_SUPPORT_SEQ_HPP

#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/concept/sequence.hpp>
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/fold_left.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/unpack.hpp>


struct Seq;

template <typename Storage>
struct seq_type {
    explicit constexpr seq_type(Storage s) : storage(s) { }
    Storage storage;
    using hana_tag = Seq;
};

struct seq_t {
    template <typename ...Xs>
    constexpr auto operator()(Xs&& ...xs) const {
        auto storage = boost::hana::make_tuple(xs...);
        return seq_type<decltype(storage)>(storage);
    }
};
constexpr seq_t seq{};

namespace boost { namespace hana {
    //////////////////////////////////////////////////////////////////////////
    // Foldable
    //
    // Define either one to select which MCD is used:
    //  BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD
    //  BOOST_HANA_TEST_FOLDABLE_UNPACK_MCD
    //  BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD
    //
    // If neither is defined, the MCD used is unspecified.
    //////////////////////////////////////////////////////////////////////////
#ifdef BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD
    template <>
    struct fold_left_impl<Seq> {
        template <typename Xs, typename S, typename F>
        static constexpr auto apply(Xs xs, S s, F f) {
            return hana::fold_left(xs.storage, s, f);
        }

        template <typename Xs, typename F>
        static constexpr auto apply(Xs xs, F f) {
            return hana::fold_left(xs.storage, f);
        }
    };
#elif defined(BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD)
    template <>
    struct length_impl<Seq> {
        template <typename Xs>
        static constexpr auto apply(Xs const& xs) {
            return hana::length(xs.storage);
        }
    };
#else
    template <>
    struct unpack_impl<Seq> {
        template <typename Xs, typename F>
        static constexpr auto apply(Xs xs, F f)
        { return hana::unpack(xs.storage, f); }
    };
#endif

    //////////////////////////////////////////////////////////////////////////
    // Iterable
    //////////////////////////////////////////////////////////////////////////
    template <>
    struct at_impl<Seq> {
        template <typename Xs, typename N>
        static constexpr decltype(auto) apply(Xs&& xs, N&& n) {
            return hana::at(static_cast<Xs&&>(xs).storage, n);
        }
    };

    template <>
    struct drop_front_impl<Seq> {
        template <typename Xs, typename N>
        static constexpr auto apply(Xs xs, N n) {
            return hana::unpack(hana::drop_front(xs.storage, n), ::seq);
        }
    };

    template <>
    struct is_empty_impl<Seq> {
        template <typename Xs>
        static constexpr auto apply(Xs xs) {
            return hana::is_empty(xs.storage);
        }
    };

    //////////////////////////////////////////////////////////////////////////
    // Sequence
    //////////////////////////////////////////////////////////////////////////
    template <>
    struct Sequence<Seq> {
        static constexpr bool value = true;
    };

    template <>
    struct make_impl<Seq> {
        template <typename ...Xs>
        static constexpr auto apply(Xs&& ...xs) {
            return ::seq(static_cast<Xs&&>(xs)...);
        }
    };
}} // end namespace boost::hana

#endif // !TEST_SUPPORT_SEQ_HPP