template struct Tuple2 { A a; B b; bool operator==(const Tuple2& x) const { return a == x.a && b == x.b; } bool operator!=(const Tuple2& x) const { return !operator==(x); } int Compare(const Tuple2& x) const { return CombineCompare(a, x.a)(b, x.b); } bool operator<=(const Tuple2& x) const { return Compare(x) <= 0; } bool operator>=(const Tuple2& x) const { return Compare(x) >= 0; } bool operator<(const Tuple2& x) const { return Compare(x) < 0; } bool operator>(const Tuple2& x) const { return Compare(x) > 0; } unsigned GetHashValue() const { return CombineHash(a, b); } void Serialize(Stream& s) { s % a % b; } String ToString() const { return String().Cat() << '(' << a << ", " << b << ')'; } template operator Tuple2() const { Tuple2 t; t.a = (AA)a; t.b = (BB)b; return t; } }; template inline void AssertMoveable0(Tuple2 *) { AssertMoveable(); AssertMoveable(); } template inline Tuple2 Tuple(const A& a, const B& b) { Tuple2 r; r.a = a; r.b = b; return r; } template inline Tuple2 MakeTuple(const A& a, const B& b) // Old name { return Tuple(a, b); } template struct Tuple3 { A a; B b; C c; bool operator==(const Tuple3& x) const { return a == x.a && b == x.b && c == x.c; } bool operator!=(const Tuple3& x) const { return !operator==(x); } int Compare(const Tuple3& x) const { return CombineCompare(a, x.a)(b, x.b)(c, x.c); } bool operator<=(const Tuple3& x) const { return Compare(x) <= 0; } bool operator>=(const Tuple3& x) const { return Compare(x) >= 0; } bool operator<(const Tuple3& x) const { return Compare(x) < 0; } bool operator>(const Tuple3& x) const { return Compare(x) > 0; } unsigned GetHashValue() const { return CombineHash(a, b, c); } void Serialize(Stream& s) { s % a % b % c; } String ToString() const { return String().Cat() << '(' << a << ", " << b << ", " << c << ')'; } template operator Tuple3() const { Tuple3 t; t.a = (AA)a; t.b = (BB)b; t.c = (CC)c; return t; } }; template inline void AssertMoveable0(Tuple3 *) { AssertMoveable(); AssertMoveable(); AssertMoveable(); } template inline Tuple3 Tuple(const A& a, const B& b, const C& c) { Tuple3 r; r.a = a; r.b = b; r.c = c; return r; } template inline Tuple3 MakeTuple(const A& a, const B& b, const C& c) { return Tuple(a, b, c); } template struct Tuple4 { A a; B b; C c; D d; bool operator==(const Tuple4& x) const { return a == x.a && b == x.b && c == x.c && d == x.d; } bool operator!=(const Tuple4& x) const { return !operator==(x); } int Compare(const Tuple4& x) const { return CombineCompare(a, x.a)(b, x.b)(c, x.c)(d, x.d); } bool operator<=(const Tuple4& x) const { return Compare(x) <= 0; } bool operator>=(const Tuple4& x) const { return Compare(x) >= 0; } bool operator<(const Tuple4& x) const { return Compare(x) < 0; } bool operator>(const Tuple4& x) const { return Compare(x) > 0; } unsigned GetHashValue() const { return CombineHash(a, b, c, d); } void Serialize(Stream& s) { s % a % b % c % d; } String ToString() const { return String().Cat() << '(' << a << ", " << b << ", " << c << ", " << d << ')'; } template operator Tuple4() const { Tuple4 t; t.a = (AA)a; t.b = (BB)b; t.c = (CC)c; t.d = (DD)d; return t; } }; template inline void AssertMoveable0(Tuple4 *) { AssertMoveable(); AssertMoveable(); AssertMoveable(); AssertMoveable(); } template inline Tuple4 Tuple(const A& a, const B& b, const C& c, const D& d) { Tuple4 r; r.a = a; r.b = b; r.c = c; r.d = d; return r; } template inline Tuple4 MakeTuple(const A& a, const B& b, const C& c, const D& d) { return Tuple(a, b, c, d); } template inline T *FindTuple(T *x, int n, const U& key) { while(n--) { if(x->a == key) return x; x++; } return NULL; } template struct Tie2 { A& a; B& b; void operator=(const Tuple2& s) { a = s.a; b = s.b; } Tie2(A& a, B& b) : a(a), b(b) {} }; template Tie2 Tie(A& a, B& b) { return Tie2(a, b); } template struct Tie3 { A& a; B& b; C& c; void operator=(const Tuple3& s) { a = s.a; b = s.b; c = s.c; } Tie3(A& a, B& b, C& c) : a(a), b(b), c(c) {} }; template Tie3 Tie(A& a, B& b, C& c) { return Tie3(a, b, c); } template struct Tie4 { A& a; B& b; C& c; D& d; void operator=(const Tuple4& s) { a = s.a; b = s.b; c = s.c; d = s.d; } Tie4(A& a, B& b, C& c, D& d) : a(a), b(b), c(c), d(d) {} }; template Tie4 Tie(A& a, B& b, C& c, D& d) { return Tie4(a, b, c, d); }