Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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. }  // namespace gtest_internal
  127.  
  128. template <>
  129. class tuple<> {
  130.  public:
  131.   tuple() {}
  132.   tuple(const tuple& /* t */)  {}
  133.   tuple& operator=(const tuple& /* t */) { return *this; }
  134. };
  135.  
  136.  
  137. $for k [[
  138. $range m 0..k-1
  139. template <GTEST_$(k)_TYPENAMES_(T)>
  140. class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
  141.  public:
  142.   template <int k> friend class gtest_internal::Get;
  143.  
  144.   tuple() : $for m, [[f$(m)_()]] {}
  145.  
  146.   explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
  147. $for m, [[f$(m)_(f$m)]] {}
  148.  
  149.   tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
  150.  
  151.   template <GTEST_$(k)_TYPENAMES_(U)>
  152.   tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
  153.  
  154. $if k == 2 [[
  155.   template <typename U0, typename U1>
  156.   tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
  157.  
  158. ]]
  159.  
  160.   tuple& operator=(const tuple& t) { return CopyFrom(t); }
  161.  
  162.   template <GTEST_$(k)_TYPENAMES_(U)>
  163.   tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
  164.     return CopyFrom(t);
  165.   }
  166.  
  167. $if k == 2 [[
  168.   template <typename U0, typename U1>
  169.   tuple& operator=(const ::std::pair<U0, U1>& p) {
  170.     f0_ = p.first;
  171.     f1_ = p.second;
  172.     return *this;
  173.   }
  174.  
  175. ]]
  176.  
  177.   GTEST_DECLARE_TUPLE_AS_FRIEND_
  178.  
  179.   template <GTEST_$(k)_TYPENAMES_(U)>
  180.   tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
  181.  
  182. $for m [[
  183.     f$(m)_ = t.f$(m)_;
  184.  
  185. ]]
  186.     return *this;
  187.   }
  188.  
  189.  
  190. $for m [[
  191.   T$m f$(m)_;
  192.  
  193. ]]
  194. };
  195.  
  196.  
  197. ]]
  198. // 6.1.3.2 Tuple creation functions.
  199.  
  200. // Known limitations: we don't support passing an
  201. // std::tr1::reference_wrapper<T> to make_tuple().  And we don't
  202. // implement tie().
  203.  
  204. inline tuple<> make_tuple() { return tuple<>(); }
  205.  
  206. $for k [[
  207. $range m 0..k-1
  208.  
  209. template <GTEST_$(k)_TYPENAMES_(T)>
  210. inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
  211.   return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
  212. }
  213.  
  214. ]]
  215.  
  216. // 6.1.3.3 Tuple helper classes.
  217.  
  218. template <typename Tuple> struct tuple_size;
  219.  
  220.  
  221. $for j [[
  222. template <GTEST_$(j)_TYPENAMES_(T)>
  223. struct tuple_size<GTEST_$(j)_TUPLE_(T)> { static const int value = $j; };
  224.  
  225.  
  226. ]]
  227. template <int k, class Tuple>
  228. struct tuple_element {
  229.   typedef typename gtest_internal::TupleElement<
  230.       k < (tuple_size<Tuple>::value), k, Tuple>::type type;
  231. };
  232.  
  233. #define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
  234.  
  235. // 6.1.3.4 Element access.
  236.  
  237. namespace gtest_internal {
  238.  
  239.  
  240. $for i [[
  241. template <>
  242. class Get<$i> {
  243.  public:
  244.   template <class Tuple>
  245.   static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
  246.   Field(Tuple& t) { return t.f$(i)_; }  // NOLINT
  247.  
  248.   template <class Tuple>
  249.   static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
  250.   ConstField(const Tuple& t) { return t.f$(i)_; }
  251. };
  252.  
  253.  
  254. ]]
  255. }  // namespace gtest_internal
  256.  
  257. template <int k, GTEST_$(n)_TYPENAMES_(T)>
  258. GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
  259. get(GTEST_$(n)_TUPLE_(T)& t) {
  260.   return gtest_internal::Get<k>::Field(t);
  261. }
  262.  
  263. template <int k, GTEST_$(n)_TYPENAMES_(T)>
  264. GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_$(n)_TUPLE_(T)))
  265. get(const GTEST_$(n)_TUPLE_(T)& t) {
  266.   return gtest_internal::Get<k>::ConstField(t);
  267. }
  268.  
  269. // 6.1.3.5 Relational operators
  270.  
  271. // We only implement == and !=, as we don't have a need for the rest yet.
  272.  
  273. namespace gtest_internal {
  274.  
  275. // SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
  276. // first k fields of t1 equals the first k fields of t2.
  277. // SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
  278. // k1 != k2.
  279. template <int kSize1, int kSize2>
  280. struct SameSizeTuplePrefixComparator;
  281.  
  282. template <>
  283. struct SameSizeTuplePrefixComparator<0, 0> {
  284.   template <class Tuple1, class Tuple2>
  285.   static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
  286.     return true;
  287.   }
  288. };
  289.  
  290. template <int k>
  291. struct SameSizeTuplePrefixComparator<k, k> {
  292.   template <class Tuple1, class Tuple2>
  293.   static bool Eq(const Tuple1& t1, const Tuple2& t2) {
  294.     return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
  295.         ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
  296.   }
  297. };
  298.  
  299. }  // namespace gtest_internal
  300.  
  301. template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
  302. inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
  303.                        const GTEST_$(n)_TUPLE_(U)& u) {
  304.   return gtest_internal::SameSizeTuplePrefixComparator<
  305.       tuple_size<GTEST_$(n)_TUPLE_(T)>::value,
  306.       tuple_size<GTEST_$(n)_TUPLE_(U)>::value>::Eq(t, u);
  307. }
  308.  
  309. template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
  310. inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
  311.                        const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
  312.  
  313. // 6.1.4 Pairs.
  314. // Unimplemented.
  315.  
  316. }  // namespace tr1
  317. }  // namespace std
  318.  
  319.  
  320. $for j [[
  321. #undef GTEST_$(j)_TUPLE_
  322.  
  323. ]]
  324.  
  325.  
  326. $for j [[
  327. #undef GTEST_$(j)_TYPENAMES_
  328.  
  329. ]]
  330.  
  331. #undef GTEST_DECLARE_TUPLE_AS_FRIEND_
  332. #undef GTEST_BY_REF_
  333. #undef GTEST_ADD_REF_
  334. #undef GTEST_TUPLE_ELEMENT_
  335.  
  336. #endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
  337.