/ src / util / vector.h
vector.h
 1  // Copyright (c) 2019-present The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  
 5  #ifndef BITCOIN_UTIL_VECTOR_H
 6  #define BITCOIN_UTIL_VECTOR_H
 7  
 8  #include <functional>
 9  #include <initializer_list>
10  #include <optional>
11  #include <type_traits>
12  #include <utility>
13  #include <vector>
14  
15  /** Construct a vector with the specified elements.
16   *
17   * This is preferable over the list initializing constructor of std::vector:
18   * - It automatically infers the element type from its arguments.
19   * - If any arguments are rvalue references, they will be moved into the vector
20   *   (list initialization always copies).
21   */
22  template<typename... Args>
23  inline std::vector<std::common_type_t<Args...>> Vector(Args&&... args)
24  {
25      std::vector<std::common_type_t<Args...>> ret;
26      ret.reserve(sizeof...(args));
27      // The line below uses the trick from https://www.experts-exchange.com/articles/32502/None-recursive-variadic-templates-with-std-initializer-list.html
28      (void)std::initializer_list<int>{(ret.emplace_back(std::forward<Args>(args)), 0)...};
29      return ret;
30  }
31  
32  /** Concatenate two vectors, moving elements. */
33  template<typename V>
34  inline V Cat(V v1, V&& v2)
35  {
36      v1.reserve(v1.size() + v2.size());
37      for (auto& arg : v2) {
38          v1.push_back(std::move(arg));
39      }
40      return v1;
41  }
42  
43  /** Concatenate two vectors. */
44  template<typename V>
45  inline V Cat(V v1, const V& v2)
46  {
47      v1.reserve(v1.size() + v2.size());
48      for (const auto& arg : v2) {
49          v1.push_back(arg);
50      }
51      return v1;
52  }
53  
54  /** Clear a vector (or std::deque) and release its allocated memory. */
55  template<typename V>
56  inline void ClearShrink(V& v) noexcept
57  {
58      // There are various ways to clear a vector and release its memory:
59      //
60      // 1. V{}.swap(v)
61      // 2. v = V{}
62      // 3. v = {}; v.shrink_to_fit();
63      // 4. v.clear(); v.shrink_to_fit();
64      //
65      // (2) does not appear to release memory in glibc debug mode, even if v.shrink_to_fit()
66      // follows. (3) and (4) rely on std::vector::shrink_to_fit, which is only a non-binding
67      // request. Therefore, we use method (1).
68  
69      V{}.swap(v);
70  }
71  
72  template<typename V, typename L>
73  inline std::optional<V> FindFirst(const std::vector<V>& vec, const L fnc)
74  {
75      for (const auto& el : vec) {
76          if (fnc(el)) {
77              return el;
78          }
79      }
80      return std::nullopt;
81  }
82  
83  #endif // BITCOIN_UTIL_VECTOR_H