Bug 1661457 - Add in-place constructor to CompactPair. r=froydnj

Differential Revision: https://phabricator.services.mozilla.com/D88418
This commit is contained in:
Simon Giesecke 2020-09-02 17:56:35 +00:00
parent 5cacc3e1dc
commit d85bd68479
2 changed files with 100 additions and 4 deletions

View File

@ -10,6 +10,7 @@
#define mozilla_CompactPair_h
#include <type_traits>
#include <tuple>
#include <utility>
#include "mozilla/Attributes.h"
@ -40,6 +41,16 @@ struct CompactPairHelper;
template <typename A, typename B>
struct CompactPairHelper<A, B, AsMember, AsMember> {
protected:
template <typename... AArgs, std::size_t... AIndexes, typename... BArgs,
std::size_t... BIndexes>
CompactPairHelper(std::tuple<AArgs...>& aATuple,
std::tuple<BArgs...>& aBTuple,
std::index_sequence<AIndexes...>,
std::index_sequence<BIndexes...>)
: mFirstA(std::forward<AArgs>(std::get<AIndexes>(aATuple))...),
mSecondB(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...) {}
public:
template <typename AArg, typename BArg>
CompactPairHelper(AArg&& aA, BArg&& aB)
: mFirstA(std::forward<AArg>(aA)), mSecondB(std::forward<BArg>(aB)) {}
@ -62,6 +73,16 @@ struct CompactPairHelper<A, B, AsMember, AsMember> {
template <typename A, typename B>
struct CompactPairHelper<A, B, AsMember, AsBase> : private B {
protected:
template <typename... AArgs, std::size_t... AIndexes, typename... BArgs,
std::size_t... BIndexes>
CompactPairHelper(std::tuple<AArgs...>& aATuple,
std::tuple<BArgs...>& aBTuple,
std::index_sequence<AIndexes...>,
std::index_sequence<BIndexes...>)
: B(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...),
mFirstA(std::forward<AArgs>(std::get<AIndexes>(aATuple))...) {}
public:
template <typename AArg, typename BArg>
CompactPairHelper(AArg&& aA, BArg&& aB)
: B(std::forward<BArg>(aB)), mFirstA(std::forward<AArg>(aA)) {}
@ -83,6 +104,16 @@ struct CompactPairHelper<A, B, AsMember, AsBase> : private B {
template <typename A, typename B>
struct CompactPairHelper<A, B, AsBase, AsMember> : private A {
protected:
template <typename... AArgs, std::size_t... AIndexes, typename... BArgs,
std::size_t... BIndexes>
CompactPairHelper(std::tuple<AArgs...>& aATuple,
std::tuple<BArgs...>& aBTuple,
std::index_sequence<AIndexes...>,
std::index_sequence<BIndexes...>)
: A(std::forward<AArgs>(std::get<AIndexes>(aATuple))...),
mSecondB(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...) {}
public:
template <typename AArg, typename BArg>
CompactPairHelper(AArg&& aA, BArg&& aB)
: A(std::forward<AArg>(aA)), mSecondB(std::forward<BArg>(aB)) {}
@ -104,6 +135,16 @@ struct CompactPairHelper<A, B, AsBase, AsMember> : private A {
template <typename A, typename B>
struct CompactPairHelper<A, B, AsBase, AsBase> : private A, private B {
protected:
template <typename... AArgs, std::size_t... AIndexes, typename... BArgs,
std::size_t... BIndexes>
CompactPairHelper(std::tuple<AArgs...>& aATuple,
std::tuple<BArgs...>& aBTuple,
std::index_sequence<AIndexes...>,
std::index_sequence<BIndexes...>)
: A(std::forward<AArgs>(std::get<AIndexes>(aATuple))...),
B(std::forward<BArgs>(std::get<BIndexes>(aBTuple))...) {}
public:
template <typename AArg, typename BArg>
CompactPairHelper(AArg&& aA, BArg&& aB)
: A(std::forward<AArg>(aA)), B(std::forward<BArg>(aB)) {}
@ -141,10 +182,13 @@ template <typename A, typename B>
struct CompactPair : private detail::CompactPairHelper<A, B> {
typedef typename detail::CompactPairHelper<A, B> Base;
public:
template <typename AArg, typename BArg>
CompactPair(AArg&& aA, BArg&& aB)
: Base(std::forward<AArg>(aA), std::forward<BArg>(aB)) {}
using Base::Base;
template <typename... AArgs, typename... BArgs>
CompactPair(std::piecewise_construct_t, std::tuple<AArgs...> aFirst,
std::tuple<BArgs...> aSecond)
: Base(aFirst, aSecond, std::index_sequence_for<AArgs...>(),
std::index_sequence_for<BArgs...>()) {}
CompactPair(CompactPair&& aOther) = default;
CompactPair(const CompactPair& aOther) = default;

View File

@ -6,6 +6,7 @@
#include <type_traits>
#include "mozilla/Assertions.h"
#include "mozilla/CompactPair.h"
using mozilla::CompactPair;
@ -67,6 +68,55 @@ INSTANTIATE(A, A, class1, 2);
INSTANTIATE(A, B, class2, 2);
INSTANTIATE(A, EmptyClass, class3, 1);
struct EmptyNonMovableNonDefaultConstructible {
explicit EmptyNonMovableNonDefaultConstructible(int) {}
EmptyNonMovableNonDefaultConstructible(
const EmptyNonMovableNonDefaultConstructible&) = delete;
EmptyNonMovableNonDefaultConstructible(
EmptyNonMovableNonDefaultConstructible&&) = delete;
EmptyNonMovableNonDefaultConstructible& operator=(
const EmptyNonMovableNonDefaultConstructible&) = delete;
EmptyNonMovableNonDefaultConstructible& operator=(
EmptyNonMovableNonDefaultConstructible&&) = delete;
};
static void TestInPlaceConstruction() {
constexpr int firstValue = 42;
constexpr int secondValue = 43;
{
const CompactPair<EmptyNonMovableNonDefaultConstructible, int> pair{
std::piecewise_construct, std::tuple(firstValue),
std::tuple(secondValue)};
MOZ_RELEASE_ASSERT(pair.second() == secondValue);
}
{
const CompactPair<int, EmptyNonMovableNonDefaultConstructible> pair{
std::piecewise_construct, std::tuple(firstValue),
std::tuple(secondValue)};
MOZ_RELEASE_ASSERT(pair.first() == firstValue);
}
{
const CompactPair<int, int> pair{std::piecewise_construct,
std::tuple(firstValue),
std::tuple(secondValue)};
MOZ_RELEASE_ASSERT(pair.first() == firstValue);
MOZ_RELEASE_ASSERT(pair.second() == secondValue);
}
{
const CompactPair<EmptyNonMovableNonDefaultConstructible,
EmptyNonMovableNonDefaultConstructible>
pair{std::piecewise_construct, std::tuple(firstValue),
std::tuple(secondValue)};
// nothing to assert here...
}
}
struct OtherEmpty : EmptyClass {
explicit OtherEmpty(int aI) : EmptyClass(aI) {}
};
@ -104,5 +154,7 @@ int main() {
a = constA;
a = A(0);
TestInPlaceConstruction();
return 0;
}