Chromium Code Reviews| Index: base/tuple.h |
| diff --git a/base/tuple.h b/base/tuple.h |
| index 16f51241392946b3c264687b77ef54998d86ac2c..014e6b41ff40a6d8720d4890b4fbd2dc93eb6af0 100644 |
| --- a/base/tuple.h |
| +++ b/base/tuple.h |
| @@ -2,20 +2,19 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -// A Tuple is a generic templatized container, similar in concept to std::pair. |
| -// There are classes Tuple0 to Tuple6, cooresponding to the number of elements |
| -// it contains. The convenient MakeTuple() function takes 0 to 6 arguments, |
| -// and will construct and return the appropriate Tuple object. The functions |
| -// DispatchToMethod and DispatchToFunction take a function pointer or instance |
| -// and method pointer, and unpack a tuple into arguments to the call. |
| +// A Tuple is a generic templatized container, similar in concept to std::pair |
| +// and std::tuple. The convenient MakeTuple() function takes any number of |
| +// arguments and will construct and return the appropriate Tuple object. The |
| +// functions DispatchToMethod and DispatchToFunction take a function pointer or |
| +// instance and method pointer, and unpack a tuple into arguments to the call. |
| // |
| // Tuple elements are copied by value, and stored in the tuple. See the unit |
| // tests for more details of how/when the values are copied. |
| // |
| // Example usage: |
| // // These two methods of creating a Tuple are identical. |
| -// Tuple2<int, const char*> tuple_a(1, "wee"); |
| -// Tuple2<int, const char*> tuple_b = MakeTuple(1, "wee"); |
| +// Tuple<int, const char*> tuple_a(1, "wee"); |
| +// Tuple<int, const char*> tuple_b = MakeTuple(1, "wee"); |
| // |
| // void SomeFunc(int a, const char* b) { } |
| // DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") |
| @@ -47,9 +46,8 @@ struct MakeIndexSequenceImpl<0, Ns...> { |
| }; |
| template <size_t N, size_t... Ns> |
| -struct MakeIndexSequenceImpl<N, Ns...> { |
| - using Type = typename MakeIndexSequenceImpl<N - 1, N - 1, Ns...>::Type; |
| -}; |
| +struct MakeIndexSequenceImpl<N, Ns...> |
| + : public MakeIndexSequenceImpl<N - 1, N - 1, Ns...> {}; |
|
tzik
2014/12/10 06:43:27
can we remove "public" since it's default for stru
mdempsky
2014/12/10 07:46:03
Done (here and below).
|
| template <size_t N> |
| using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::Type; |
| @@ -83,215 +81,74 @@ struct TupleTraits<P&> { |
| // function objects that need to take an arbitrary number of parameters; see |
| // RunnableMethod and IPC::MessageWithTuple. |
| // |
| -// Tuple0 is supplied to act as a 'void' type. It can be used, for example, |
| +// Tuple<> is supplied to act as a 'void' type. It can be used, for example, |
| // when dispatching to a function that accepts no arguments (see the |
| // Dispatchers below). |
| -// Tuple1<A> is rarely useful. One such use is when A is non-const ref that you |
| +// Tuple<A> is rarely useful. One such use is when A is non-const ref that you |
| // want filled by the dispatchee, and the tuple is merely a container for that |
| // output (a "tier"). See MakeRefTuple and its usages. |
| +template <typename IxSeq, typename... Ts> |
| +struct TupleBaseImpl; |
| template <typename... Ts> |
| -struct Tuple; |
| - |
| -template <> |
| -struct Tuple<> {}; |
| - |
| -template <typename A> |
| -struct Tuple<A> { |
| - public: |
| - typedef A TypeA; |
| - |
| - Tuple() {} |
| - explicit Tuple(typename TupleTraits<A>::ParamType a) : a(a) {} |
| +using TupleBase = TupleBaseImpl<MakeIndexSequence<sizeof...(Ts)>, Ts...>; |
| +template <size_t N, typename T> |
| +struct TupleLeaf; |
| - A a; |
| +template <typename... Ts> |
| +struct Tuple : public TupleBase<Ts...> { |
| + Tuple() : TupleBase<Ts...>() {} |
|
Nico
2014/12/10 07:00:31
Isn't this the same as the constructor in the line
mdempsky
2014/12/10 07:15:23
If I understand your question: "for Tuple<>, would
mdempsky
2014/12/10 07:46:03
(On the chance that issue was the Tuple<> speciali
|
| + explicit Tuple(typename TupleTraits<Ts>::ParamType... args) |
| + : TupleBase<Ts...>(args...) {} |
| }; |
| -template <typename A, typename B> |
| -struct Tuple<A, B> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b) |
| - : a(a), b(b) {} |
| - |
| - A a; |
| - B b; |
| +template <size_t... Ns, typename... Ts> |
| +struct TupleBaseImpl<IndexSequence<Ns...>, Ts...> |
| + : public TupleLeaf<Ns, Ts>... { |
| + TupleBaseImpl() : TupleLeaf<Ns, Ts>()... {} |
|
Nico
2014/12/10 07:00:31
same question
|
| + explicit TupleBaseImpl(typename TupleTraits<Ts>::ParamType... args) |
| + : TupleLeaf<Ns, Ts>(args)... {} |
| }; |
| -template <typename A, typename B, typename C> |
| -struct Tuple<A, B, C> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - typedef C TypeC; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b, |
| - typename TupleTraits<C>::ParamType c) |
| - : a(a), b(b), c(c) {} |
| - |
| - A a; |
| - B b; |
| - C c; |
| -}; |
| +template <size_t N, typename T> |
| +struct TupleLeaf { |
| + TupleLeaf() : x() {} |
| + explicit TupleLeaf(typename TupleTraits<T>::ParamType x) : x(x) {} |
| -template <typename A, typename B, typename C, typename D> |
| -struct Tuple<A, B, C, D> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - typedef C TypeC; |
| - typedef D TypeD; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b, |
| - typename TupleTraits<C>::ParamType c, |
| - typename TupleTraits<D>::ParamType d) |
| - : a(a), b(b), c(c), d(d) {} |
| - |
| - A a; |
| - B b; |
| - C c; |
| - D d; |
| -}; |
| + T& get() { return x; } |
| + const T& get() const { return x; } |
| -template <typename A, typename B, typename C, typename D, typename E> |
| -struct Tuple<A, B, C, D, E> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - typedef C TypeC; |
| - typedef D TypeD; |
| - typedef E TypeE; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b, |
| - typename TupleTraits<C>::ParamType c, |
| - typename TupleTraits<D>::ParamType d, |
| - typename TupleTraits<E>::ParamType e) |
| - : a(a), b(b), c(c), d(d), e(e) {} |
| - |
| - A a; |
| - B b; |
| - C c; |
| - D d; |
| - E e; |
| + T x; |
| }; |
| -template <typename A, |
| - typename B, |
| - typename C, |
| - typename D, |
| - typename E, |
| - typename F> |
| -struct Tuple<A, B, C, D, E, F> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - typedef C TypeC; |
| - typedef D TypeD; |
| - typedef E TypeE; |
| - typedef F TypeF; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b, |
| - typename TupleTraits<C>::ParamType c, |
| - typename TupleTraits<D>::ParamType d, |
| - typename TupleTraits<E>::ParamType e, |
| - typename TupleTraits<F>::ParamType f) |
| - : a(a), b(b), c(c), d(d), e(e), f(f) {} |
| - |
| - A a; |
| - B b; |
| - C c; |
| - D d; |
| - E e; |
| - F f; |
| -}; |
| - |
| -template <typename A, |
| - typename B, |
| - typename C, |
| - typename D, |
| - typename E, |
| - typename F, |
| - typename G> |
| -struct Tuple<A, B, C, D, E, F, G> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - typedef C TypeC; |
| - typedef D TypeD; |
| - typedef E TypeE; |
| - typedef F TypeF; |
| - typedef G TypeG; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b, |
| - typename TupleTraits<C>::ParamType c, |
| - typename TupleTraits<D>::ParamType d, |
| - typename TupleTraits<E>::ParamType e, |
| - typename TupleTraits<F>::ParamType f, |
| - typename TupleTraits<G>::ParamType g) |
| - : a(a), b(b), c(c), d(d), e(e), f(f), g(g) {} |
| - |
| - A a; |
| - B b; |
| - C c; |
| - D d; |
| - E e; |
| - F f; |
| - G g; |
| -}; |
| +// Avoids ambiguity between Tuple's two constructors. |
| +template <> |
| +struct Tuple<> {}; |
| -template <typename A, |
| - typename B, |
| - typename C, |
| - typename D, |
| - typename E, |
| - typename F, |
| - typename G, |
| - typename H> |
| -struct Tuple<A, B, C, D, E, F, G, H> { |
| - public: |
| - typedef A TypeA; |
| - typedef B TypeB; |
| - typedef C TypeC; |
| - typedef D TypeD; |
| - typedef E TypeE; |
| - typedef F TypeF; |
| - typedef G TypeG; |
| - typedef H TypeH; |
| - |
| - Tuple() {} |
| - Tuple(typename TupleTraits<A>::ParamType a, |
| - typename TupleTraits<B>::ParamType b, |
| - typename TupleTraits<C>::ParamType c, |
| - typename TupleTraits<D>::ParamType d, |
| - typename TupleTraits<E>::ParamType e, |
| - typename TupleTraits<F>::ParamType f, |
| - typename TupleTraits<G>::ParamType g, |
| - typename TupleTraits<H>::ParamType h) |
| - : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) {} |
| - |
| - A a; |
| - B b; |
| - C c; |
| - D d; |
| - E e; |
| - F f; |
| - G g; |
| - H h; |
| -}; |
| +// For legacy compatibility, we name the first 8 tuple elements "a", "b", ... |
|
Nico
2014/12/10 07:00:31
Does it make sense to remove all clients of this a
mdempsky
2014/12/10 07:46:03
Done.
|
| + |
| +#define DEFINE_TUPLE_LEAF(N, x) \ |
| + template <typename T> \ |
| + struct TupleLeaf<N, T> { \ |
| + TupleLeaf() : x() {} \ |
| + explicit TupleLeaf(typename TupleTraits<T>::ParamType x) : x(x) {} \ |
| + \ |
| + T& get() { return x; } \ |
| + const T& get() const { return x; } \ |
| + \ |
| + T x; \ |
| + } |
| + |
| +DEFINE_TUPLE_LEAF(0, a); |
| +DEFINE_TUPLE_LEAF(1, b); |
| +DEFINE_TUPLE_LEAF(2, c); |
| +DEFINE_TUPLE_LEAF(3, d); |
| +DEFINE_TUPLE_LEAF(4, e); |
| +DEFINE_TUPLE_LEAF(5, f); |
| +DEFINE_TUPLE_LEAF(6, g); |
| +DEFINE_TUPLE_LEAF(7, h); |
| + |
| +#undef DEFINE_TUPLE_LEAF |
| // Deprecated compat aliases |
| @@ -333,89 +190,29 @@ using Tuple8 = Tuple<A, B, C, D, E, F, G, H>; |
| // Tuple element -------------------------------------------------------------- |
| -template <size_t N, typename T> |
| -struct TupleElement; |
| +template <size_t N, typename... Ts> |
| +struct NthType; |
| template <typename T, typename... Ts> |
| -struct TupleElement<0, Tuple<T, Ts...>> { |
| +struct NthType<0, T, Ts...> { |
| using Type = T; |
| }; |
| template <size_t N, typename T, typename... Ts> |
| -struct TupleElement<N, Tuple<T, Ts...>> { |
| - using Type = typename TupleElement<N - 1, Tuple<Ts...>>::Type; |
| -}; |
| +struct NthType<N, T, Ts...> : public NthType<N - 1, Ts...> {}; |
| // Tuple getters -------------------------------------------------------------- |
| -template <size_t, typename T> |
| -struct TupleGetter; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<0, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<0, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.a; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.a; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<1, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<1, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.b; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.b; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<2, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<2, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.c; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.c; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<3, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<3, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.d; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.d; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<4, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<4, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.e; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.e; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<5, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<5, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.f; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.f; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<6, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<6, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.g; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.g; } |
| -}; |
| - |
| -template <typename... Ts> |
| -struct TupleGetter<7, Tuple<Ts...>> { |
| - using Elem = typename TupleElement<7, Tuple<Ts...>>::Type; |
| - static Elem& Get(Tuple<Ts...>& t) { return t.h; } |
| - static const Elem& Get(const Tuple<Ts...>& t) { return t.h; } |
| -}; |
| - |
| template <size_t I, typename... Ts> |
| -typename TupleElement<I, Tuple<Ts...>>::Type& get(Tuple<Ts...>& tuple) { |
| - return TupleGetter<I, Tuple<Ts...>>::Get(tuple); |
| +typename NthType<I, Ts...>::Type& get(Tuple<Ts...>& tuple) { |
|
tzik
2014/12/10 06:43:27
If it works, how about matching the tuple against
mdempsky
2014/12/10 07:46:03
Nice, seems to work, and means NthType isn't neede
|
| + using Elem = typename NthType<I, Ts...>::Type; |
| + return static_cast<TupleLeaf<I, Elem>&>(tuple).get(); |
| } |
| template <size_t I, typename... Ts> |
| -const typename TupleElement<I, Tuple<Ts...>>::Type& get( |
| - const Tuple<Ts...>& tuple) { |
| - return TupleGetter<I, Tuple<Ts...>>::Get(tuple); |
| +const typename NthType<I, Ts...>::Type& get(const Tuple<Ts...>& tuple) { |
| + using Elem = typename NthType<I, Ts...>::Type; |
| + return static_cast<const TupleLeaf<I, Elem>&>(tuple).get(); |
| } |
| // Tuple types ---------------------------------------------------------------- |