Bug 1184385 - Add a Tie() utility function for tuples (the equivalent of std::tie()) to MFBT. r=froydnj

--HG--
extra : rebase_source : 5d6ce0668782e4f3339dbca0d15e2202b566c6b3
extra : source : 9f736422e7903a20560bb83d1832f85a28b89880
This commit is contained in:
Botond Ballo 2015-07-18 03:48:39 -04:00
parent 20a6d72138
commit f1d4fcd69b
2 changed files with 83 additions and 2 deletions

View File

@ -142,7 +142,30 @@ struct TupleImpl<Index, HeadT, TailT...>
, mHead(Head(aOther)) {}
TupleImpl(TupleImpl&& aOther)
: Base(Move(Tail(aOther)))
, mHead(Move(Head(aOther))) {}
, mHead(Forward<HeadT>(Head(aOther))) {}
// Assign from a tuple whose elements are convertible to the elements
// of this tuple.
template <typename... OtherElements,
typename = typename EnableIf<
sizeof...(OtherElements) == sizeof...(TailT) + 1>::Type>
TupleImpl& operator=(const TupleImpl<Index, OtherElements...>& aOther)
{
typedef TupleImpl<Index, OtherElements...> OtherT;
Head(*this) = OtherT::Head(aOther);
Tail(*this) = OtherT::Tail(aOther);
return *this;
}
template <typename... OtherElements,
typename = typename EnableIf<
sizeof...(OtherElements) == sizeof...(TailT) + 1>::Type>
TupleImpl& operator=(TupleImpl<Index, OtherElements...>&& aOther)
{
typedef TupleImpl<Index, OtherElements...> OtherT;
Head(*this) = Move(OtherT::Head(aOther));
Tail(*this) = Move(OtherT::Tail(aOther));
return *this;
}
// Copy and move assignment operators.
TupleImpl& operator=(const TupleImpl& aOther)
@ -195,6 +218,22 @@ public:
Tuple(const Tuple& aOther) : Impl(aOther) { }
Tuple(Tuple&& aOther) : Impl(Move(aOther)) { }
template <typename... OtherElements,
typename = typename EnableIf<
sizeof...(OtherElements) == sizeof...(Elements)>::Type>
Tuple& operator=(const Tuple<OtherElements...>& aOther)
{
static_cast<Impl&>(*this) = aOther;
return *this;
}
template <typename... OtherElements,
typename = typename EnableIf<
sizeof...(OtherElements) == sizeof...(Elements)>::Type>
Tuple& operator=(Tuple<OtherElements...>&& aOther)
{
static_cast<Impl&>(*this) = Move(aOther);
return *this;
}
Tuple& operator=(const Tuple& aOther)
{
static_cast<Impl&>(*this) = aOther;
@ -296,6 +335,25 @@ Tuple<Elements...> MakeTuple(Elements&&... aElements)
return Tuple<Elements...>(Forward<Elements>(aElements)...);
}
/**
* A convenience function for constructing a tuple of references to a
* sequence of variables. Since assignments to the elements of the tuple
* "go through" to the referenced variables, this can be used to "unpack"
* a tuple into individual variables.
*
* Example:
*
* int i;
* float f;
* char c;
* Tie(i, f, c) = FunctionThatReturnsATuple();
*/
template<typename... Elements>
Tuple<Elements&...> Tie(Elements&... aVariables)
{
return Tuple<Elements&...>(aVariables...);
}
} // namespace mozilla
#endif /* mozilla_Tuple_h */

View File

@ -18,6 +18,7 @@ using mozilla::IsSame;
using mozilla::MakeTuple;
using mozilla::MakeUnique;
using mozilla::Move;
using mozilla::Tie;
using mozilla::Tuple;
using mozilla::UniquePtr;
using mozilla::unused;
@ -36,7 +37,7 @@ using mozilla::unused;
struct ConvertibleToInt
{
operator int() { return 42; }
operator int() const { return 42; }
};
static void
@ -136,6 +137,27 @@ TestMakeTuple()
return true;
}
static bool
TestTie()
{
int i;
float f;
char c;
Tuple<int, float, char> rhs1(42, 0.5f, 'c');
Tie(i, f, c) = rhs1;
CHECK(i == Get<0>(rhs1));
CHECK(f == Get<1>(rhs1));
CHECK(c == Get<2>(rhs1));
// Test conversions
Tuple<ConvertibleToInt, double, unsigned char> rhs2(ConvertibleToInt(),
0.7f, 'd');
Tie(i, f, c) = rhs2;
CHECK(i == Get<0>(rhs2));
CHECK(f == Get<1>(rhs2));
CHECK(c == Get<2>(rhs2));
return true;
}
int
main()
{
@ -143,5 +165,6 @@ main()
TestAssignment();
TestGet();
TestMakeTuple();
TestTie();
return 0;
}