You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
9.0 KiB

  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. // Implements a subset of TR1 tuple needed by Google Test and Google Mock.
  35. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
  36. #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
  37. #include <utility> // For ::std::pair.
  38. // The compiler used in Symbian has a bug that prevents us from declaring the
  39. // tuple template as a friend (it complains that tuple is redefined). This
  40. // hack bypasses the bug by declaring the members that should otherwise be
  41. // private as public.
  42. // Sun Studio versions < 12 also have the above bug.
  43. #if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
  44. # define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
  45. #else
  46. # define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
  47. template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
  48. private:
  49. #endif
  50. $range i 0..n-1
  51. $range j 0..n
  52. $range k 1..n
  53. // GTEST_n_TUPLE_(T) is the type of an n-tuple.
  54. #define GTEST_0_TUPLE_(T) tuple<>
  55. $for k [[
  56. $range m 0..k-1
  57. $range m2 k..n-1
  58. #define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
  59. ]]
  60. // GTEST_n_TYPENAMES_(T) declares a list of n typenames.
  61. $for j [[
  62. $range m 0..j-1
  63. #define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
  64. ]]
  65. // In theory, defining stuff in the ::std namespace is undefined
  66. // behavior. We can do this as we are playing the role of a standard
  67. // library vendor.
  68. namespace std {
  69. namespace tr1 {
  70. template <$for i, [[typename T$i = void]]>
  71. class tuple;
  72. // Anything in namespace gtest_internal is Google Test's INTERNAL
  73. // IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
  74. namespace gtest_internal {
  75. // ByRef<T>::type is T if T is a reference; otherwise it's const T&.
  76. template <typename T>
  77. struct ByRef { typedef const T& type; }; // NOLINT
  78. template <typename T>
  79. struct ByRef<T&> { typedef T& type; }; // NOLINT
  80. // A handy wrapper for ByRef.
  81. #define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
  82. // AddRef<T>::type is T if T is a reference; otherwise it's T&. This
  83. // is the same as tr1::add_reference<T>::type.
  84. template <typename T>
  85. struct AddRef { typedef T& type; }; // NOLINT
  86. template <typename T>
  87. struct AddRef<T&> { typedef T& type; }; // NOLINT
  88. // A handy wrapper for AddRef.
  89. #define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
  90. // A helper for implementing get<k>().
  91. template <int k> class Get;
  92. // A helper for implementing tuple_element<k, T>. kIndexValid is true
  93. // iff k < the number of fields in tuple type T.
  94. template <bool kIndexValid, int kIndex, class Tuple>
  95. struct TupleElement;
  96. $for i [[
  97. template <GTEST_$(n)_TYPENAMES_(T)>
  98. struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T)> [[]]
  99. { typedef T$i type; };
  100. ]]
  101. } // namespace gtest_internal
  102. template <>
  103. class tuple<> {
  104. public:
  105. tuple() {}
  106. tuple(const tuple& /* t */) {}
  107. tuple& operator=(const tuple& /* t */) { return *this; }
  108. };
  109. $for k [[
  110. $range m 0..k-1
  111. template <GTEST_$(k)_TYPENAMES_(T)>
  112. class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
  113. public:
  114. template <int k> friend class gtest_internal::Get;
  115. tuple() : $for m, [[f$(m)_()]] {}
  116. explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
  117. $for m, [[f$(m)_(f$m)]] {}
  118. tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
  119. template <GTEST_$(k)_TYPENAMES_(U)>
  120. tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
  121. $if k == 2 [[
  122. template <typename U0, typename U1>
  123. tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
  124. ]]
  125. tuple& operator=(const tuple& t) { return CopyFrom(t); }
  126. template <GTEST_$(k)_TYPENAMES_(U)>
  127. tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
  128. return CopyFrom(t);
  129. }
  130. $if k == 2 [[
  131. template <typename U0, typename U1>
  132. tuple& operator=(const ::std::pair<U0, U1>& p) {
  133. f0_ = p.first;
  134. f1_ = p.second;
  135. return *this;
  136. }
  137. ]]
  138. GTEST_DECLARE_TUPLE_AS_FRIEND_
  139. template <GTEST_$(k)_TYPENAMES_(U)>
  140. tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
  141. $for m [[
  142. f$(m)_ = t.f$(m)_;
  143. ]]
  144. return *this;
  145. }
  146. $for m [[
  147. T$m f$(m)_;
  148. ]]
  149. };
  150. ]]
  151. // 6.1.3.2 Tuple creation functions.
  152. // Known limitations: we don't support passing an
  153. // std::tr1::reference_wrapper<T> to make_tuple(). And we don't
  154. // implement tie().
  155. inline tuple<> make_tuple() { return tuple<>(); }
  156. $for k [[
  157. $range m 0..k-1
  158. template <GTEST_$(k)_TYPENAMES_(T)>
  159. inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
  160. return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
  161. }
  162. ]]
  163. // 6.1.3.3 Tuple helper classes.
  164. template <typename Tuple> struct tuple_size;
  165. $for j [[
  166. template <GTEST_$(j)_TYPENAMES_(T)>
  167. struct tuple_size<GTEST_$(j)_TUPLE_(T)> { static const int value = $j; };
  168. ]]
  169. template <int k, class Tuple>
  170. struct tuple_element {
  171. typedef typename gtest_internal::TupleElement<
  172. k < (tuple_size<Tuple>::value), k, Tuple>::type type;
  173. };
  174. #define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
  175. // 6.1.3.4 Element access.
  176. namespace gtest_internal {
  177. $for i [[
  178. template <>
  179. class Get<$i> {
  180. public:
  181. template <class Tuple>
  182. static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
  183. Field(Tuple& t) { return t.f$(i)_; } // NOLINT
  184. template <class Tuple>
  185. static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
  186. ConstField(const Tuple& t) { return t.f$(i)_; }
  187. };
  188. ]]
  189. } // namespace gtest_internal
  190. template <int k, GTEST_$(n)_TYPENAMES_(T)>
  191. GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
  192. get(GTEST_$(n)_TUPLE_(T)& t) {
  193. return gtest_internal::Get<k>::Field(t);
  194. }
  195. template <int k, GTEST_$(n)_TYPENAMES_(T)>
  196. GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
  197. get(const GTEST_$(n)_TUPLE_(T)& t) {
  198. return gtest_internal::Get<k>::ConstField(t);
  199. }
  200. // 6.1.3.5 Relational operators
  201. // We only implement == and !=, as we don't have a need for the rest yet.
  202. namespace gtest_internal {
  203. // SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
  204. // first k fields of t1 equals the first k fields of t2.
  205. // SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
  206. // k1 != k2.
  207. template <int kSize1, int kSize2>
  208. struct SameSizeTuplePrefixComparator;
  209. template <>
  210. struct SameSizeTuplePrefixComparator<0, 0> {
  211. template <class Tuple1, class Tuple2>
  212. static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
  213. return true;
  214. }
  215. };
  216. template <int k>
  217. struct SameSizeTuplePrefixComparator<k, k> {
  218. template <class Tuple1, class Tuple2>
  219. static bool Eq(const Tuple1& t1, const Tuple2& t2) {
  220. return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
  221. ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
  222. }
  223. };
  224. } // namespace gtest_internal
  225. template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
  226. inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
  227. const GTEST_$(n)_TUPLE_(U)& u) {
  228. return gtest_internal::SameSizeTuplePrefixComparator<
  229. tuple_size<GTEST_$(n)_TUPLE_(T)>::value,
  230. tuple_size<GTEST_$(n)_TUPLE_(U)>::value>::Eq(t, u);
  231. }
  232. template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
  233. inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
  234. const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
  235. // 6.1.4 Pairs.
  236. // Unimplemented.
  237. } // namespace tr1
  238. } // namespace std
  239. $for j [[
  240. #undef GTEST_$(j)_TUPLE_
  241. ]]
  242. $for j [[
  243. #undef GTEST_$(j)_TYPENAMES_
  244. ]]
  245. #undef GTEST_DECLARE_TUPLE_AS_FRIEND_
  246. #undef GTEST_BY_REF_
  247. #undef GTEST_ADD_REF_
  248. #undef GTEST_TUPLE_ELEMENT_
  249. #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_