vector.h raw

   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
  84