1$$ -*- mode: c++; -*-
2$var n = 10  $$ Maximum number of tuple fields we want to support.
3$$ This meta comment fixes auto-indentation in Emacs. }}
4// Copyright 2009 Google Inc.
5// All Rights Reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met:
10//
11//     * Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//     * Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17//     * Neither the name of Google Inc. nor the names of its
18// contributors may be used to endorse or promote products derived from
19// this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// Author: wan@google.com (Zhanyong Wan)
34
35// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
36
37#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
38#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
39
40#include <utility>  // For ::std::pair.
41
42// The compiler used in Symbian 5th Edition (__S60_50__) has a bug
43// that prevents us from declaring the tuple template as a friend (it
44// complains that tuple is redefined).  This hack bypasses the bug by
45// declaring the members that should otherwise be private as public.
46#if defined(__SYMBIAN32__) && __S60_50__
47#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
48#else
49#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
50    template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
51   private:
52#endif
53
54
55$range i 0..n-1
56$range j 0..n
57$range k 1..n
58// GTEST_n_TUPLE_(T) is the type of an n-tuple.
59#define GTEST_0_TUPLE_(T) tuple<>
60
61$for k [[
62$range m 0..k-1
63$range m2 k..n-1
64#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
65
66]]
67
68// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
69
70$for j [[
71$range m 0..j-1
72#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
73
74
75]]
76
77// In theory, defining stuff in the ::std namespace is undefined
78// behavior.  We can do this as we are playing the role of a standard
79// library vendor.
80namespace std {
81namespace tr1 {
82
83template <$for i, [[typename T$i = void]]>
84class tuple;
85
86// Anything in namespace gtest_internal is Google Test's INTERNAL
87// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
88namespace gtest_internal {
89
90// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
91template <typename T>
92struct ByRef { typedef const T& type; };  // NOLINT
93template <typename T>
94struct ByRef<T&> { typedef T& type; };  // NOLINT
95
96// A handy wrapper for ByRef.
97#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
98
99// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
100// is the same as tr1::add_reference<T>::type.
101template <typename T>
102struct AddRef { typedef T& type; };  // NOLINT
103template <typename T>
104struct AddRef<T&> { typedef T& type; };  // NOLINT
105
106// A handy wrapper for AddRef.
107#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
108
109// A helper for implementing get<k>().
110template <int k> class Get;
111
112// A helper for implementing tuple_element<k, T>.  kIndexValid is true
113// iff k < the number of fields in tuple type T.
114template <bool kIndexValid, int kIndex, class Tuple>
115struct TupleElement;
116
117
118$for i [[
119template <GTEST_$(n)_TYPENAMES_(T)>
120struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T)> [[]]
121{ typedef T$i type; };
122
123
124]]
125}  // namespace gtest_internal
126
127template <>
128class tuple<> {
129 public:
130  tuple() {}
131  tuple(const tuple& /* t */)  {}
132  tuple& operator=(const tuple& /* t */) { return *this; }
133};
134
135
136$for k [[
137$range m 0..k-1
138template <GTEST_$(k)_TYPENAMES_(T)>
139class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
140 public:
141  template <int k> friend class gtest_internal::Get;
142
143  tuple() {}
144
145  explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
146$for m, [[f$(m)_(f$m)]] {}
147
148  tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
149
150  template <GTEST_$(k)_TYPENAMES_(U)>
151  tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
152
153$if k == 2 [[
154  template <typename U0, typename U1>
155  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
156
157]]
158
159  tuple& operator=(const tuple& t) { return CopyFrom(t); }
160
161  template <GTEST_$(k)_TYPENAMES_(U)>
162  tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
163    return CopyFrom(t);
164  }
165
166$if k == 2 [[
167  template <typename U0, typename U1>
168  tuple& operator=(const ::std::pair<U0, U1>& p) {
169    f0_ = p.first;
170    f1_ = p.second;
171    return *this;
172  }
173
174]]
175
176  GTEST_DECLARE_TUPLE_AS_FRIEND_
177
178  template <GTEST_$(k)_TYPENAMES_(U)>
179  tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
180
181$for m [[
182    f$(m)_ = t.f$(m)_;
183
184]]
185    return *this;
186  }
187
188
189$for m [[
190  T$m f$(m)_;
191
192]]
193};
194
195
196]]
197// 6.1.3.2 Tuple creation functions.
198
199// Known limitations: we don't support passing an
200// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
201// implement tie().
202
203inline tuple<> make_tuple() { return tuple<>(); }
204
205$for k [[
206$range m 0..k-1
207
208template <GTEST_$(k)_TYPENAMES_(T)>
209inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
210  return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
211}
212
213]]
214
215// 6.1.3.3 Tuple helper classes.
216
217template <typename Tuple> struct tuple_size;
218
219
220$for j [[
221template <GTEST_$(j)_TYPENAMES_(T)>
222struct tuple_size<GTEST_$(j)_TUPLE_(T)> { static const int value = $j; };
223
224
225]]
226template <int k, class Tuple>
227struct tuple_element {
228  typedef typename gtest_internal::TupleElement<
229      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
230};
231
232#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
233
234// 6.1.3.4 Element access.
235
236namespace gtest_internal {
237
238
239$for i [[
240template <>
241class Get<$i> {
242 public:
243  template <class Tuple>
244  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
245  Field(Tuple& t) { return t.f$(i)_; }  // NOLINT
246
247  template <class Tuple>
248  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
249  ConstField(const Tuple& t) { return t.f$(i)_; }
250};
251
252
253]]
254}  // namespace gtest_internal
255
256template <int k, GTEST_$(n)_TYPENAMES_(T)>
257GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
258get(GTEST_$(n)_TUPLE_(T)& t) {
259  return gtest_internal::Get<k>::Field(t);
260}
261
262template <int k, GTEST_$(n)_TYPENAMES_(T)>
263GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_$(n)_TUPLE_(T)))
264get(const GTEST_$(n)_TUPLE_(T)& t) {
265  return gtest_internal::Get<k>::ConstField(t);
266}
267
268// 6.1.3.5 Relational operators
269
270// We only implement == and !=, as we don't have a need for the rest yet.
271
272namespace gtest_internal {
273
274// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
275// first k fields of t1 equals the first k fields of t2.
276// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
277// k1 != k2.
278template <int kSize1, int kSize2>
279struct SameSizeTuplePrefixComparator;
280
281template <>
282struct SameSizeTuplePrefixComparator<0, 0> {
283  template <class Tuple1, class Tuple2>
284  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
285    return true;
286  }
287};
288
289template <int k>
290struct SameSizeTuplePrefixComparator<k, k> {
291  template <class Tuple1, class Tuple2>
292  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
293    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
294        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
295  }
296};
297
298}  // namespace gtest_internal
299
300template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
301inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
302                       const GTEST_$(n)_TUPLE_(U)& u) {
303  return gtest_internal::SameSizeTuplePrefixComparator<
304      tuple_size<GTEST_$(n)_TUPLE_(T)>::value,
305      tuple_size<GTEST_$(n)_TUPLE_(U)>::value>::Eq(t, u);
306}
307
308template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
309inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
310                       const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
311
312// 6.1.4 Pairs.
313// Unimplemented.
314
315}  // namespace tr1
316}  // namespace std
317
318
319$for j [[
320#undef GTEST_$(j)_TUPLE_
321
322]]
323
324
325$for j [[
326#undef GTEST_$(j)_TYPENAMES_
327
328]]
329
330#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
331#undef GTEST_BY_REF_
332#undef GTEST_ADD_REF_
333#undef GTEST_TUPLE_ELEMENT_
334
335#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
336