Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.
  81. namespace std {
  82. namespace tr1 {
  83.  
  84. template <$for i, [[typename T$i = void]]>
  85. class 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.
  89. namespace gtest_internal {
  90.  
  91. // ByRef<T>::type is T if T is a reference; otherwise it's const T&.
  92. template <typename T>
  93. struct ByRef { typedef const T& type; };  // NOLINT
  94. template <typename T>
  95. struct 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.
  102. template <typename T>
  103. struct AddRef { typedef T& type; };  // NOLINT
  104. template <typename T>
  105. struct 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>().
  111. template <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.
  115. template <bool kIndexValid, int kIndex, class Tuple>
  116. struct TupleElement;
  117.  
  118.  
  119. $for i [[
  120. template <GTEST_$(n)_TYPENAMES_(T)>
  121. struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
  122.   typedef T$i type;
  123. };
  124.  
  125.  
  126. ]]
  127. }  // namespace gtest_internal
  128.  
  129. template <>
  130. class 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
  140. template <GTEST_$(k)_TYPENAMES_(T)>
  141. class $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.  
  205. inline tuple<> make_tuple() { return tuple<>(); }
  206.  
  207. $for k [[
  208. $range m 0..k-1
  209.  
  210. template <GTEST_$(k)_TYPENAMES_(T)>
  211. inline 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.  
  219. template <typename Tuple> struct tuple_size;
  220.  
  221.  
  222. $for j [[
  223. template <GTEST_$(j)_TYPENAMES_(T)>
  224. struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
  225.   static const int value = $j;
  226. };
  227.  
  228.  
  229. ]]
  230. template <int k, class Tuple>
  231. struct 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.  
  240. namespace gtest_internal {
  241.  
  242.  
  243. $for i [[
  244. template <>
  245. class 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.  
  260. template <int k, GTEST_$(n)_TYPENAMES_(T)>
  261. GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
  262. get(GTEST_$(n)_TUPLE_(T)& t) {
  263.   return gtest_internal::Get<k>::Field(t);
  264. }
  265.  
  266. template <int k, GTEST_$(n)_TYPENAMES_(T)>
  267. GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_$(n)_TUPLE_(T)))
  268. get(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.  
  276. namespace 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.
  282. template <int kSize1, int kSize2>
  283. struct SameSizeTuplePrefixComparator;
  284.  
  285. template <>
  286. struct 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.  
  293. template <int k>
  294. struct 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.  
  304. template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
  305. inline 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.  
  312. template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
  313. inline 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.