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