Line data Source code
1 : // Copyright (c) 2019-2022 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 <initializer_list> 9 : #include <type_traits> 10 : #include <utility> 11 : #include <vector> 12 : 13 : /** Construct a vector with the specified elements. 14 : * 15 : * This is preferable over the list initializing constructor of std::vector: 16 : * - It automatically infers the element type from its arguments. 17 : * - If any arguments are rvalue references, they will be moved into the vector 18 : * (list initialization always copies). 19 : */ 20 : template<typename... Args> 21 32 : inline std::vector<typename std::common_type<Args...>::type> Vector(Args&&... args) 22 : { 23 32 : std::vector<typename std::common_type<Args...>::type> ret; 24 32 : ret.reserve(sizeof...(args)); 25 : // The line below uses the trick from https://www.experts-exchange.com/articles/32502/None-recursive-variadic-templates-with-std-initializer-list.html 26 32 : (void)std::initializer_list<int>{(ret.emplace_back(std::forward<Args>(args)), 0)...}; 27 32 : return ret; 28 32 : } 29 : 30 : /** Concatenate two vectors, moving elements. */ 31 : template<typename V> 32 3 : inline V Cat(V v1, V&& v2) 33 : { 34 3 : v1.reserve(v1.size() + v2.size()); 35 21 : for (auto& arg : v2) { 36 18 : v1.push_back(std::move(arg)); 37 : } 38 3 : return v1; 39 : } 40 : 41 : /** Concatenate two vectors. */ 42 : template<typename V> 43 138 : inline V Cat(V v1, const V& v2) 44 : { 45 138 : v1.reserve(v1.size() + v2.size()); 46 280 : for (const auto& arg : v2) { 47 142 : v1.push_back(arg); 48 : } 49 138 : return v1; 50 : } 51 : 52 : /** Clear a vector (or std::deque) and release its allocated memory. */ 53 : template<typename V> 54 0 : inline void ClearShrink(V& v) noexcept 55 : { 56 : // There are various ways to clear a vector and release its memory: 57 : // 58 : // 1. V{}.swap(v) 59 : // 2. v = V{} 60 : // 3. v = {}; v.shrink_to_fit(); 61 : // 4. v.clear(); v.shrink_to_fit(); 62 : // 63 : // (2) does not appear to release memory in glibc debug mode, even if v.shrink_to_fit() 64 : // follows. (3) and (4) rely on std::vector::shrink_to_fit, which is only a non-binding 65 : // request. Therefore, we use method (1). 66 : 67 0 : V{}.swap(v); 68 0 : } 69 : 70 : #endif // BITCOIN_UTIL_VECTOR_H