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 has a bug that prevents us from declaring the 43// tuple template as a friend (it complains that tuple is redefined). This 44// hack bypasses the bug by declaring the members that should otherwise be 45// private as public. 46// Sun Studio versions < 12 also have the above bug. 47#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) 48# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: 49#else 50# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ 51 template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \ 52 private: 53#endif 54 55 56$range i 0..n-1 57$range j 0..n 58$range k 1..n 59// GTEST_n_TUPLE_(T) is the type of an n-tuple. 60#define GTEST_0_TUPLE_(T) tuple<> 61 62$for k [[ 63$range m 0..k-1 64$range m2 k..n-1 65#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]> 66 67]] 68 69// GTEST_n_TYPENAMES_(T) declares a list of n typenames. 70 71$for j [[ 72$range m 0..j-1 73#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]] 74 75 76]] 77 78// In theory, defining stuff in the ::std namespace is undefined 79// behavior. We can do this as we are playing the role of a standard 80// library vendor. 81namespace std { 82namespace tr1 { 83 84template <$for i, [[typename T$i = void]]> 85class tuple; 86 87// Anything in namespace gtest_internal is Google Test's INTERNAL 88// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. 89namespace gtest_internal { 90 91// ByRef<T>::type is T if T is a reference; otherwise it's const T&. 92template <typename T> 93struct ByRef { typedef const T& type; }; // NOLINT 94template <typename T> 95struct ByRef<T&> { typedef T& type; }; // NOLINT 96 97// A handy wrapper for ByRef. 98#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type 99 100// AddRef<T>::type is T if T is a reference; otherwise it's T&. This 101// is the same as tr1::add_reference<T>::type. 102template <typename T> 103struct AddRef { typedef T& type; }; // NOLINT 104template <typename T> 105struct AddRef<T&> { typedef T& type; }; // NOLINT 106 107// A handy wrapper for AddRef. 108#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type 109 110// A helper for implementing get<k>(). 111template <int k> class Get; 112 113// A helper for implementing tuple_element<k, T>. kIndexValid is true 114// iff k < the number of fields in tuple type T. 115template <bool kIndexValid, int kIndex, class Tuple> 116struct TupleElement; 117 118 119$for i [[ 120template <GTEST_$(n)_TYPENAMES_(T)> 121struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > { 122 typedef T$i type; 123}; 124 125 126]] 127} // namespace gtest_internal 128 129template <> 130class tuple<> { 131 public: 132 tuple() {} 133 tuple(const tuple& /* t */) {} 134 tuple& operator=(const tuple& /* t */) { return *this; } 135}; 136 137 138$for k [[ 139$range m 0..k-1 140template <GTEST_$(k)_TYPENAMES_(T)> 141class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] { 142 public: 143 template <int k> friend class gtest_internal::Get; 144 145 tuple() : $for m, [[f$(m)_()]] {} 146 147 explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]] 148$for m, [[f$(m)_(f$m)]] {} 149 150 tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 151 152 template <GTEST_$(k)_TYPENAMES_(U)> 153 tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 154 155$if k == 2 [[ 156 template <typename U0, typename U1> 157 tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {} 158 159]] 160 161 tuple& operator=(const tuple& t) { return CopyFrom(t); } 162 163 template <GTEST_$(k)_TYPENAMES_(U)> 164 tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) { 165 return CopyFrom(t); 166 } 167 168$if k == 2 [[ 169 template <typename U0, typename U1> 170 tuple& operator=(const ::std::pair<U0, U1>& p) { 171 f0_ = p.first; 172 f1_ = p.second; 173 return *this; 174 } 175 176]] 177 178 GTEST_DECLARE_TUPLE_AS_FRIEND_ 179 180 template <GTEST_$(k)_TYPENAMES_(U)> 181 tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) { 182 183$for m [[ 184 f$(m)_ = t.f$(m)_; 185 186]] 187 return *this; 188 } 189 190 191$for m [[ 192 T$m f$(m)_; 193 194]] 195}; 196 197 198]] 199// 6.1.3.2 Tuple creation functions. 200 201// Known limitations: we don't support passing an 202// std::tr1::reference_wrapper<T> to make_tuple(). And we don't 203// implement tie(). 204 205inline tuple<> make_tuple() { return tuple<>(); } 206 207$for k [[ 208$range m 0..k-1 209 210template <GTEST_$(k)_TYPENAMES_(T)> 211inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) { 212 return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]); 213} 214 215]] 216 217// 6.1.3.3 Tuple helper classes. 218 219template <typename Tuple> struct tuple_size; 220 221 222$for j [[ 223template <GTEST_$(j)_TYPENAMES_(T)> 224struct tuple_size<GTEST_$(j)_TUPLE_(T) > { 225 static const int value = $j; 226}; 227 228 229]] 230template <int k, class Tuple> 231struct tuple_element { 232 typedef typename gtest_internal::TupleElement< 233 k < (tuple_size<Tuple>::value), k, Tuple>::type type; 234}; 235 236#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type 237 238// 6.1.3.4 Element access. 239 240namespace gtest_internal { 241 242 243$for i [[ 244template <> 245class Get<$i> { 246 public: 247 template <class Tuple> 248 static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 249 Field(Tuple& t) { return t.f$(i)_; } // NOLINT 250 251 template <class Tuple> 252 static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 253 ConstField(const Tuple& t) { return t.f$(i)_; } 254}; 255 256 257]] 258} // namespace gtest_internal 259 260template <int k, GTEST_$(n)_TYPENAMES_(T)> 261GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 262get(GTEST_$(n)_TUPLE_(T)& t) { 263 return gtest_internal::Get<k>::Field(t); 264} 265 266template <int k, GTEST_$(n)_TYPENAMES_(T)> 267GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 268get(const GTEST_$(n)_TUPLE_(T)& t) { 269 return gtest_internal::Get<k>::ConstField(t); 270} 271 272// 6.1.3.5 Relational operators 273 274// We only implement == and !=, as we don't have a need for the rest yet. 275 276namespace gtest_internal { 277 278// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the 279// first k fields of t1 equals the first k fields of t2. 280// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if 281// k1 != k2. 282template <int kSize1, int kSize2> 283struct SameSizeTuplePrefixComparator; 284 285template <> 286struct SameSizeTuplePrefixComparator<0, 0> { 287 template <class Tuple1, class Tuple2> 288 static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { 289 return true; 290 } 291}; 292 293template <int k> 294struct SameSizeTuplePrefixComparator<k, k> { 295 template <class Tuple1, class Tuple2> 296 static bool Eq(const Tuple1& t1, const Tuple2& t2) { 297 return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) && 298 ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2); 299 } 300}; 301 302} // namespace gtest_internal 303 304template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)> 305inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t, 306 const GTEST_$(n)_TUPLE_(U)& u) { 307 return gtest_internal::SameSizeTuplePrefixComparator< 308 tuple_size<GTEST_$(n)_TUPLE_(T) >::value, 309 tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u); 310} 311 312template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)> 313inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t, 314 const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); } 315 316// 6.1.4 Pairs. 317// Unimplemented. 318 319} // namespace tr1 320} // namespace std 321 322 323$for j [[ 324#undef GTEST_$(j)_TUPLE_ 325 326]] 327 328 329$for j [[ 330#undef GTEST_$(j)_TYPENAMES_ 331 332]] 333 334#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ 335#undef GTEST_BY_REF_ 336#undef GTEST_ADD_REF_ 337#undef GTEST_TUPLE_ELEMENT_ 338 339#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 340