summaryrefslogtreecommitdiff
path: root/tiger-compiler/lib/misc/algorithm.hxx
blob: 00ca8adb963c1b15a0177d869b52f91f0150e30c (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
/**
 ** \file misc/algorithm.hxx
 ** \brief Some syntactic sugar to look for things in STL containers.
 */

#pragma once

#include <algorithm>
#include <functional>
#include <ostream>

#include <misc/algorithm.hh>

namespace misc
{
  template <typename Container>
    requires Iterable<Container>
  void deep_clear(Container& c)
  {
    for (typename Container::value_type& x : c)
      delete x;
    c.clear();
  }

  // Find \a v in the whole \a c.
  template <typename Container>
    requires ConstIterable<Container>
  inline typename Container::const_iterator
  find(const Container& c, const typename Container::value_type& v)
  {
    return std::find(c.begin(), c.end(), v);
  }

  // Find \a v in the whole \a c.
  template <typename Container>
    requires Iterable<Container>
  inline typename Container::iterator
  find(Container& c, const typename Container::value_type& v)
  {
    return std::find(c.begin(), c.end(), v);
  }

  // Apply \a f to all the members of \a c, and return it.
  template <typename Container, typename Functor>
    requires ConstIterable<Container>
  inline Functor& for_each(Container& c, Functor& f)
  {
    std::ranges::for_each(c, std::ref(f));
    return f;
  }

  // Is \a v member of \a c?
  template <typename Container>
    requires ConstIterable<Container>
  inline bool has(const Container& c, const typename Container::value_type& v)
  {
    // We specify the instance to solve a conflict between the
    // two finds above, that compete against each other because
    // the parameter Container can embed a "const".
    return std::ranges::find(c, v) != c.end();
  }

  template <Map Map>
  typename Map::iterator put(Map& map,
                             const typename Map::key_type& key,
                             const typename Map::mapped_type& value)
  {
    // See ``Efficient STL''.
    auto i = map.lower_bound(key);

    if (i != map.end() && !(map.key_comp()(key, i->first)))
      {
        // Update.
        i->second = value;
        return i;
      }
    else
      {
        // First insertion.
        return map.emplace(key, value).first;
      }
  }

} // namespace misc