Bug 1185706 - support Tie() for mozilla::Pair. r=froydnj

This commit is contained in:
Liang-Heng Chen 2015-07-24 00:42:00 +02:00
parent d33d8a52f0
commit 236aa9654e
2 changed files with 207 additions and 0 deletions

View File

@ -10,10 +10,12 @@
#define mozilla_Tuple_h
#include "mozilla/Move.h"
#include "mozilla/Pair.h"
#include "mozilla/TemplateLib.h"
#include "mozilla/TypeTraits.h"
#include <stddef.h>
#include <utility>
namespace mozilla {
@ -246,6 +248,91 @@ public:
}
};
/**
* Specialization of Tuple for two elements.
* This is created to support construction and assignment from a Pair or std::pair.
*/
template <typename A, typename B>
class Tuple<A, B> : public detail::TupleImpl<0, A, B>
{
typedef detail::TupleImpl<0, A, B> Impl;
public:
// The constructors and assignment operators here are simple wrappers
// around those in TupleImpl.
Tuple() : Impl() { }
explicit Tuple(const A& aA, const B& aB) : Impl(aA, aB) { }
template <typename AArg, typename BArg,
typename = typename EnableIf<
detail::CheckConvertibility<
detail::Group<AArg, BArg>,
detail::Group<A, B>>::value>::Type>
explicit Tuple(AArg&& aA, BArg&& aB)
: Impl(Forward<AArg>(aA), Forward<BArg>(aB)) { }
Tuple(const Tuple& aOther) : Impl(aOther) { }
Tuple(Tuple&& aOther) : Impl(Move(aOther)) { }
explicit Tuple(const Pair<A, B>& aOther)
: Impl(aOther.first(), aOther.second()) { }
explicit Tuple(Pair<A, B>&& aOther) : Impl(Forward<A>(aOther.first()),
Forward<B>(aOther.second())) { }
explicit Tuple(const std::pair<A, B>& aOther)
: Impl(aOther.first, aOther.second) { }
explicit Tuple(std::pair<A, B>&& aOther) : Impl(Forward<A>(aOther.first),
Forward<B>(aOther.second)) { }
template <typename AArg, typename BArg>
Tuple& operator=(const Tuple<AArg, BArg>& aOther)
{
static_cast<Impl&>(*this) = aOther;
return *this;
}
template <typename AArg, typename BArg>
Tuple& operator=(Tuple<AArg, BArg>&& aOther)
{
static_cast<Impl&>(*this) = Move(aOther);
return *this;
}
Tuple& operator=(const Tuple& aOther)
{
static_cast<Impl&>(*this) = aOther;
return *this;
}
Tuple& operator=(Tuple&& aOther)
{
static_cast<Impl&>(*this) = Move(aOther);
return *this;
}
template <typename AArg, typename BArg>
Tuple& operator=(const Pair<AArg, BArg>& aOther)
{
Impl::Head(*this) = aOther.first();
Impl::Tail(*this).Head(*this) = aOther.second();
return *this;
}
template <typename AArg, typename BArg>
Tuple& operator=(Pair<AArg, BArg>&& aOther)
{
Impl::Head(*this) = Forward<AArg>(aOther.first());
Impl::Tail(*this).Head(*this) = Forward<BArg>(aOther.second());
return *this;
}
template <typename AArg, typename BArg>
Tuple& operator=(const std::pair<AArg, BArg>& aOther)
{
Impl::Head(*this) = aOther.first;
Impl::Tail(*this).Head(*this) = aOther.second;
return *this;
}
template <typename AArg, typename BArg>
Tuple& operator=(std::pair<AArg, BArg>&& aOther)
{
Impl::Head(*this) = Forward<AArg>(aOther.first);
Impl::Tail(*this).Head(*this) = Forward<BArg>(aOther.second);
return *this;
}
};
/**
* Specialization of Tuple for zero arguments.
* This is necessary because if the primary template were instantiated with

View File

@ -6,22 +6,26 @@
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
#include "mozilla/Pair.h"
#include "mozilla/Tuple.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/unused.h"
#include <stddef.h>
#include <utility>
using mozilla::Get;
using mozilla::IsSame;
using mozilla::MakeTuple;
using mozilla::MakeUnique;
using mozilla::Move;
using mozilla::Pair;
using mozilla::Tie;
using mozilla::Tuple;
using mozilla::UniquePtr;
using mozilla::unused;
using std::pair;
#define CHECK(c) \
do { \
@ -78,6 +82,40 @@ TestConstruction()
CHECK(*Get<0>(h) == 42);
}
static void
TestConstructionFromMozPair()
{
// Construction from elements
int x = 1, y = 1;
Pair<int, int> a{x, y};
Pair<int&, const int&> b{x, y};
Tuple<int, int> c(a);
Tuple<int&, const int&> d(b);
x = 42;
y = 42;
CHECK(Get<0>(c) == 1);
CHECK(Get<1>(c) == 1);
CHECK(Get<0>(d) == 42);
CHECK(Get<1>(d) == 42);
}
static void
TestConstructionFromStdPair()
{
// Construction from elements
int x = 1, y = 1;
pair<int, int> a{x, y};
pair<int&, const int&> b{x, y};
Tuple<int, int> c(a);
Tuple<int&, const int&> d(b);
x = 42;
y = 42;
CHECK(Get<0>(c) == 1);
CHECK(Get<1>(c) == 1);
CHECK(Get<0>(d) == 42);
CHECK(Get<1>(d) == 42);
}
static void
TestAssignment()
{
@ -103,6 +141,72 @@ TestAssignment()
CHECK(Get<0>(f) == nullptr);
}
static void
TestAssignmentFromMozPair()
{
// Copy assignment
Tuple<int, int> a{0, 0};
Pair<int, int> b{42, 42};
a = b;
CHECK(Get<0>(a) == 42);
CHECK(Get<1>(a) == 42);
// Assignment to reference member
int i = 0;
int j = 0;
int k = 42;
Tuple<int&, int&> c{i, j};
Pair<int&, int&> d{k, k};
c = d;
CHECK(i == 42);
CHECK(j == 42);
// Move assignment
Tuple<UniquePtr<int>, UniquePtr<int>> e{MakeUnique<int>(0),
MakeUnique<int>(0)};
Pair<UniquePtr<int>, UniquePtr<int>> f{MakeUnique<int>(42),
MakeUnique<int>(42)};
e = Move(f);
CHECK(*Get<0>(e) == 42);
CHECK(*Get<1>(e) == 42);
CHECK(f.first() == nullptr);
CHECK(f.second() == nullptr);
}
static void
TestAssignmentFromStdPair()
{
// Copy assignment
Tuple<int, int> a{0, 0};
pair<int, int> b{42, 42};
a = b;
CHECK(Get<0>(a) == 42);
CHECK(Get<1>(a) == 42);
// Assignment to reference member
int i = 0;
int j = 0;
int k = 42;
Tuple<int&, int&> c{i, j};
pair<int&, int&> d{k, k};
c = d;
CHECK(i == 42);
CHECK(j == 42);
// Move assignment.
Tuple<UniquePtr<int>, UniquePtr<int>> e{MakeUnique<int>(0), MakeUnique<int>(0)};
// XXX: On some platforms std::pair doesn't support move constructor.
pair<UniquePtr<int>, UniquePtr<int>> f;
f.first = MakeUnique<int>(42);
f.second = MakeUnique<int>(42);
e = Move(f);
CHECK(*Get<0>(e) == 42);
CHECK(*Get<1>(e) == 42);
CHECK(f.first == nullptr);
CHECK(f.second == nullptr);
}
static void
TestGet()
{
@ -155,6 +259,18 @@ TestTie()
CHECK(i == Get<0>(rhs2));
CHECK(f == Get<1>(rhs2));
CHECK(c == Get<2>(rhs2));
// Test Pair
Pair<int, float> rhs3(-1, 1.2f);
Tie(i, f) = rhs3;
CHECK(i == rhs3.first());
CHECK(f == rhs3.second());
pair<int, float> rhs4(42, 1.5f);
Tie(i, f) = rhs4;
CHECK(i == rhs4.first);
CHECK(f == rhs4.second);
return true;
}
@ -162,7 +278,11 @@ int
main()
{
TestConstruction();
TestConstructionFromMozPair();
TestConstructionFromStdPair();
TestAssignment();
TestAssignmentFromMozPair();
TestAssignmentFromStdPair();
TestGet();
TestMakeTuple();
TestTie();