CompactPair.h (3371B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* A class holding a pair of objects that tries to conserve storage space. */ 8 9 #ifndef mozilla_CompactPair_h 10 #define mozilla_CompactPair_h 11 12 #include "mozilla/Attributes.h" 13 14 #include <cstddef> 15 #include <tuple> 16 #include <type_traits> 17 #include <utility> 18 19 namespace mozilla { 20 21 /** 22 * CompactPair is the logical concatenation of an instance of A with an instance 23 * B. Space is conserved when possible. 24 * 25 * In general if space conservation is not critical is preferred to use 26 * std::pair. 27 * 28 */ 29 template <typename A, typename B> 30 class CompactPair { 31 MOZ_NO_UNIQUE_ADDRESS A mFirst; 32 MOZ_NO_UNIQUE_ADDRESS B mSecond; 33 34 template <class APack, size_t... AIs, class BPack, size_t... BIs> 35 constexpr CompactPair(APack&& aFirst, std::index_sequence<AIs...>, 36 BPack&& aSecond, std::index_sequence<BIs...>) 37 : mFirst(std::get<AIs>(aFirst)...), mSecond(std::get<BIs>(aSecond)...) {} 38 39 public: 40 template <typename... AArgs, typename... BArgs> 41 constexpr CompactPair(std::piecewise_construct_t, std::tuple<AArgs...> aFirst, 42 std::tuple<BArgs...> aSecond) 43 : CompactPair(aFirst, std::make_index_sequence<sizeof...(AArgs)>(), 44 aSecond, std::make_index_sequence<sizeof...(BArgs)>()) {} 45 46 template <typename U, typename V> 47 explicit constexpr CompactPair(U&& aFirst, V&& aSecond) 48 : mFirst(std::forward<U>(aFirst)), mSecond(std::forward<V>(aSecond)) {} 49 CompactPair(CompactPair&& aOther) = default; 50 CompactPair(const CompactPair& aOther) = default; 51 52 CompactPair& operator=(CompactPair&& aOther) = default; 53 CompactPair& operator=(const CompactPair& aOther) = default; 54 55 constexpr A& first() { return mFirst; } 56 constexpr const A& first() const { return mFirst; } 57 constexpr B& second() { return mSecond; } 58 constexpr const B& second() const { return mSecond; } 59 60 /** Swap this pair with another pair. */ 61 void swap(CompactPair& aOther) { 62 using std::swap; 63 swap(mFirst, aOther.mFirst); 64 swap(mSecond, aOther.mSecond); 65 } 66 }; 67 68 /** 69 * MakeCompactPair allows you to construct a CompactPair instance using type 70 * inference. A call like this: 71 * 72 * MakeCompactPair(Foo(), Bar()) 73 * 74 * will return a CompactPair<Foo, Bar>. 75 */ 76 template <typename A, typename B> 77 CompactPair<std::remove_cv_t<std::remove_reference_t<A>>, 78 std::remove_cv_t<std::remove_reference_t<B>>> 79 MakeCompactPair(A&& aA, B&& aB) { 80 return CompactPair<std::remove_cv_t<std::remove_reference_t<A>>, 81 std::remove_cv_t<std::remove_reference_t<B>>>( 82 std::forward<A>(aA), std::forward<B>(aB)); 83 } 84 85 /** 86 * CompactPair equality comparison 87 */ 88 template <typename A, typename B> 89 bool operator==(const CompactPair<A, B>& aLhs, const CompactPair<A, B>& aRhs) { 90 return aLhs.first() == aRhs.first() && aLhs.second() == aRhs.second(); 91 } 92 93 } // namespace mozilla 94 95 namespace std { 96 97 template <typename A, class B> 98 void swap(mozilla::CompactPair<A, B>& aX, mozilla::CompactPair<A, B>& aY) { 99 aX.swap(aY); 100 } 101 102 } // namespace std 103 104 #endif /* mozilla_CompactPair_h */