Advertisement
Guest User

Untitled

a guest
Jun 6th, 2014
1,329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.97 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. // Helper namespace that uses SFINAE to check for certain operators.
  4. namespace check_operator_impl {
  5. typedef char NO;
  6. typedef char YES[2];
  7.  
  8. struct Any {
  9.   template <typename T> Any(T const&);
  10. };
  11.  
  12. NO operator <  (const Any&, const Any&);
  13. NO operator <= (const Any&, const Any&);
  14. NO operator == (const Any&, const Any&);
  15. NO operator >= (const Any&, const Any&);
  16. NO operator >  (const Any&, const Any&);
  17. NO operator != (const Any&, const Any&);
  18.  
  19. YES& test(bool);
  20. NO test(NO);
  21.  
  22. template <typename T> struct HasLessThanOperator
  23. { static const T& t; static bool const value = sizeof(test(t <  t)) == sizeof(YES); };
  24. template <typename T> struct HasLessThanOrEqualOperator
  25. { static const T& t; static bool const value = sizeof(test(t <= t)) == sizeof(YES); };
  26. template <typename T> struct HasEqualOperator
  27. { static const T& t; static bool const value = sizeof(test(t == t)) == sizeof(YES); };
  28. template <typename T> struct HasGreaterThanOrEqualOperator
  29. { static const T& t; static bool const value = sizeof(test(t >= t)) == sizeof(YES); };
  30. template <typename T> struct HasGreaterThanOperator
  31. { static const T& t; static bool const value = sizeof(test(t >  t)) == sizeof(YES); };
  32. template <typename T> struct HasUnequalOperator
  33. { static const T& t; static bool const value = sizeof(test(t != t)) == sizeof(YES); };
  34.  
  35. }
  36.  
  37. // The actual value container.
  38. template <typename T>
  39. struct ValueBase
  40. {
  41.   ValueBase() { }
  42.   ValueBase(const T& value) : m_value(value) { }
  43.   const T& value() const { return m_value; }
  44.   T& value() { return m_value; }
  45.   T m_value;
  46. };
  47.  
  48. // Wrappers for various common operators.
  49. template <typename T, typename Meaning, bool do_wrap>
  50. struct WrapLessThanOperatorImpl : public virtual ValueBase<T> { };
  51. template <typename T, typename Meaning, bool do_wrap>
  52. struct WrapLessThanOrEqualOperatorImpl : public virtual ValueBase<T> { };
  53. template <typename T, typename Meaning, bool do_wrap>
  54. struct WrapEqualOperatorImpl : public virtual ValueBase<T> { };
  55. template <typename T, typename Meaning, bool do_wrap>
  56. struct WrapGreaterThanOrEqualOperatorImpl : public virtual ValueBase<T> { };
  57. template <typename T, typename Meaning, bool do_wrap>
  58. struct WrapGreaterThanOperatorImpl : public virtual ValueBase<T> { };
  59. template <typename T, typename Meaning, bool do_wrap>
  60. struct WrapUnequalOperatorImpl : public virtual ValueBase<T> { };
  61.  
  62. // Wrap the operators if T has such operators.
  63. template <typename T, typename Meaning>
  64. struct WrapLessThanOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
  65. {
  66.   bool operator < (const WrapLessThanOperatorImpl<T, Meaning, true>& other)
  67.   { return ValueBase<T>::value() < other.ValueBase<T>::value(); }
  68. };
  69.  
  70. template <typename T, typename Meaning>
  71. struct WrapLessThanOrEqualOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
  72. {
  73.   bool operator <= (const WrapLessThanOrEqualOperatorImpl<T, Meaning, true>& other)
  74.   { return ValueBase<T>::value() <= other.ValueBase<T>::value(); }
  75. };
  76.  
  77. template <typename T, typename Meaning>
  78. struct WrapEqualOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
  79. {
  80.   bool operator == (const WrapEqualOperatorImpl<T, Meaning, true>& other)
  81.   { return ValueBase<T>::value() == other.ValueBase<T>::value(); }
  82. };
  83.  
  84. template <typename T, typename Meaning>
  85. struct WrapGreaterThanOrEqualOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
  86. {
  87.   bool operator>= (const WrapGreaterThanOrEqualOperatorImpl<T, Meaning, true>& other)
  88.   { return ValueBase<T>::value() >= other.ValueBase<T>::value(); }
  89. };
  90.  
  91. template <typename T, typename Meaning>
  92. struct WrapGreaterThanOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
  93. {
  94.   bool operator > (const WrapGreaterThanOperatorImpl<T, Meaning, true>& other)
  95.   { return ValueBase<T>::value() > other.ValueBase<T>::value(); }
  96. };
  97.  
  98. template <typename T, typename Meaning>
  99. struct WrapUnequalOperatorImpl<T, Meaning, true> : public virtual ValueBase<T>
  100. {
  101.   bool operator != (const WrapUnequalOperatorImpl<T, Meaning, true>& other)
  102.   { return ValueBase<T>::value() != other.ValueBase<T>::value(); }
  103. };
  104.  
  105. // These wrappers are just for convenience.
  106. template <typename T, typename Meaning>
  107. struct WrapLessThanOperator
  108.   : public WrapLessThanOperatorImpl<
  109.   T, Meaning,
  110.   check_operator_impl::HasLessThanOperator<T>::value>
  111. { };
  112.  
  113. template <typename T, typename Meaning>
  114. struct WrapLessThanOrEqualOperator
  115.   : public WrapLessThanOrEqualOperatorImpl<
  116.   T, Meaning,
  117.   check_operator_impl::HasLessThanOrEqualOperator<T>::value>
  118. { };
  119.  
  120. template <typename T, typename Meaning>
  121. struct WrapEqualOperator
  122.   : public WrapEqualOperatorImpl<
  123.   T, Meaning,
  124.   check_operator_impl::HasEqualOperator<T>::value>
  125. { };
  126.  
  127. template <typename T, typename Meaning>
  128. struct WrapGreaterThanOrEqualOperator
  129.   : public WrapGreaterThanOrEqualOperatorImpl<
  130.   T, Meaning,
  131.   check_operator_impl::HasGreaterThanOrEqualOperator<T>::value>
  132. { };
  133.  
  134. template <typename T, typename Meaning>
  135. struct WrapGreaterThanOperator
  136.   : public WrapGreaterThanOperatorImpl<
  137.   T, Meaning,
  138.   check_operator_impl::HasGreaterThanOperator<T>::value>
  139. { };
  140.  
  141. template <typename T, typename Meaning>
  142. struct WrapUnequalOperator
  143.   : public WrapUnequalOperatorImpl<
  144.   T, Meaning,
  145.   check_operator_impl::HasUnequalOperator<T>::value>
  146. { };
  147.  
  148. // Now for the actual Explicit class.
  149. template <typename T, typename Meaning>
  150. struct Explicit : public WrapLessThanOperator<T, Meaning>,
  151.                   public WrapLessThanOrEqualOperator<T, Meaning>,
  152.                   public WrapEqualOperator<T, Meaning>,
  153.                   public WrapGreaterThanOrEqualOperator<T, Meaning>,
  154.                   public WrapGreaterThanOperator<T, Meaning>,
  155.                   public WrapUnequalOperator<T, Meaning>
  156. {
  157.   //! Default constructor does not initialize the value.
  158.   Explicit()
  159.   { }
  160.  
  161.   //! Construction from a fundamental value.
  162.   Explicit(const T& value)
  163.     : ValueBase<T>(value)
  164.   { }
  165.  
  166.   Explicit& operator = (const T& value_)
  167.   { ValueBase<T>::value() = value_; return *this; }
  168. };
  169.  
  170. // Define some tags.
  171. namespace internal {
  172. struct EntityIDTag { };
  173. struct ModelIDTag { };
  174. }
  175.  
  176. // Some explicit integers
  177. typedef Explicit<int, internal::EntityIDTag> EntityID;
  178. typedef Explicit<int, internal::ModelIDTag> ModelID;
  179.  
  180. // Let's make some explicit Foos, just to show that it works if you
  181. // don't have all the operators.
  182. struct Foo
  183. {
  184.   Foo() { }
  185.   explicit Foo(int value) : value(value) { }
  186.   int value;
  187.   bool operator < (const Foo& other) const { return value < other.value; }
  188. };
  189.  
  190. typedef Explicit<Foo, internal::EntityIDTag> EntityFoo;
  191. typedef Explicit<Foo, internal::ModelIDTag> ModelFoo;
  192.  
  193. int main()
  194. {
  195.   EntityID e1 = 1, e2 = 2;
  196.   ModelID m1 = 3, m2 = 4;
  197.   EntityFoo e3(Foo(5));
  198.   ModelFoo m3(Foo(6));
  199.  
  200.   m1 = m2; // OK
  201.   // e1 = m1; // no match for 'operator=' in 'e1 = m1'
  202.   if (e1 == e2) { } // OK
  203.   if (e1 <= e2) { } // OK
  204.   // if (m1 == e2) { } // no match for operator==
  205.   // if (e3 == e3) { } // Foo has no operator==
  206.   if (e3 < e3) { } // OK, operator exists
  207.  
  208.   return 0;
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement