summaryrefslogtreecommitdiffhomepage
path: root/compat/functional.hpp
blob: dcba05380d4a4e41f2cdb730968a0f68f4f249d2 (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
#pragma once

#include "value-templates.hpp"

#include <algorithm>
#include <iterator>
#include <type_traits>
#include <vector>

namespace functools
{

template<typename seq_, typename = void>
struct reserver_
{
    static inline void maybe_reserve_space(seq_&, unsigned)
    {
        //qDebug() << "nada";
    }
};

template<typename seq_>
struct reserver_<seq_, decltype(std::declval<seq_>().reserve(0u), (void)0)>
{
    static inline void maybe_reserve_space(seq_& seq, unsigned sz)
    {
        seq.reserve(sz);
    }
};

template<typename seq_>
inline void maybe_reserve_space(seq_& seq, unsigned sz)
{
    reserver_<seq_, void>::maybe_reserve_space(seq, sz);
}

} // ns

template<typename t, t value_>
struct constant final
{
    using type = t;
    constexpr type operator()() const noexcept
    {
        return value_;
    }
    static constexpr type value = value_;

    constant() = delete;
};

template<typename seq_, typename F>
auto map(F&& fun, const seq_& seq)
{
    using value_type = std::decay_t<typename std::iterator_traits<decltype(std::begin(seq))>::value_type>;
    using ret_type = std::decay_t<decltype(fun(std::declval<value_type>()))>;

    std::vector<ret_type> ret;
    auto it = std::back_inserter(ret);

    for (const auto& elt : seq)
        it = fun(elt);

    return ret;
}

template<typename seq_, typename F>
auto remove_if_not(F&& fun, const seq_& seq)
{
    using namespace functools;

    using seq_type = std::decay_t<seq_>;
    using value_type = std::decay_t<typename std::iterator_traits<decltype(std::begin(seq))>::value_type>;
    using fun_ret_type = decltype(fun(std::declval<value_type>()));
    static_assert(is_convertible_v<fun_ret_type, bool>, "must return bool");

    seq_type ret;
    maybe_reserve_space(ret, seq.size());

    std::back_insert_iterator<seq_type> it = std::back_inserter(ret);

    for (const value_type& elt : seq)
        if (fun(elt))
            it = elt;

    return ret;
}