Advertisement
andybuckley

C++ logical object combiner (for analysis cuts)

Dec 23rd, 2012
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.69 KB | None | 0 0
  1. #include <iostream>
  2. #include "boost/static_assert.hpp"
  3. #include <boost/type_traits.hpp>
  4. #include <boost/utility.hpp>
  5. #include <boost/any.hpp>
  6. using namespace std;
  7.  
  8.  
  9. /// Base class for all cut functors (toy classifier of ints)
  10. struct Cut {
  11.   virtual bool cut(int n) const = 0;
  12. };
  13.  
  14. // Various cut functors operating on ints
  15. struct Odd : public Cut {
  16.   bool cut(int n) const { return n % 2 == 1; }
  17. };
  18. struct Even : public Cut {
  19.   bool cut(int n) const { return n % 2 == 0; }
  20. };
  21. struct Less : public Cut {
  22.   Less(int n) : val(n) { }
  23.   bool cut(int n) const { return n < val; }
  24.   int val;
  25. };
  26. struct LessEq : public Cut {
  27.   LessEq(int n) : val(n) { }
  28.   bool cut(int n) const { return n <= val; }
  29.   int val;
  30. };
  31.  
  32.  
  33. // AND, OR and NOT objects for combining cuts
  34.  
  35. template <typename CUT1, typename CUT2>
  36. struct CutsOr : public Cut {
  37.   CutsOr(const CUT1& c1, const CUT2& c2) : cut1(c1), cut2(c2) { }
  38.   bool cut(int n) const { return cut1.cut(n) || cut2.cut(n); }
  39.   CUT1 cut1;
  40.   CUT2 cut2;
  41.   BOOST_STATIC_ASSERT((boost::is_base_of<Cut, CUT1>::value && boost::is_base_of<Cut, CUT2>::value));
  42. };
  43. template <typename CUT1, typename CUT2>
  44. struct CutsAnd : public Cut {
  45.   CutsAnd(const CUT1& c1, const CUT2& c2) : cut1(c1), cut2(c2) { }
  46.   bool cut(int n) const { return cut1.cut(n) && cut2.cut(n); }
  47.   CUT1 cut1;
  48.   CUT2 cut2;
  49.   BOOST_STATIC_ASSERT((boost::is_base_of<Cut, CUT1>::value && boost::is_base_of<Cut, CUT2>::value));
  50. };
  51. template <typename CUT>
  52. struct CutInvert : public Cut {
  53.   CutInvert(const CUT& c1) : poscut(c1) { }
  54.   bool cut(int n) const { return !poscut.cut(n); }
  55.   CUT poscut;
  56.   BOOST_STATIC_ASSERT((boost::is_base_of<Cut, CUT>::value));
  57. };
  58.  
  59.  
  60. // operator &&, operator ||, and operator ! overloads
  61. //
  62. // The enable_if complexity is needed to avoid too-global template type matching;
  63. // the code below is equivalent to simply
  64. //
  65. //   template <typename CUT1, typename CUT2>
  66. //   CutsAnd<CUT1,CUT2> operator && (const CUT1& a, const CUT2& b) { ... }
  67. //
  68. //   template <typename CUT1, typename CUT2>
  69. //   CutsAnd<CUT1,CUT2> operator || (const CUT1& a, const CUT2& b) { ... }
  70. //
  71. //   template <typename CUT>
  72. //   CutInvert<CUT> operator ! (const CUT& c) { ... }
  73.  
  74. template <typename CUT1, typename CUT2>
  75. typename boost::enable_if_c<
  76.   boost::is_base_of<Cut, CUT1>::value && boost::is_base_of<Cut, CUT2>::value,
  77.   CutsAnd<CUT1,CUT2>
  78.   >::type
  79. operator && (const CUT1& a, const CUT2& b) {
  80.   return CutsAnd<CUT1,CUT2>(a,b);
  81. }
  82.  
  83. template <typename CUT1, typename CUT2>
  84. typename boost::enable_if_c<
  85.   boost::is_base_of<Cut, CUT1>::value && boost::is_base_of<Cut, CUT2>::value,
  86.   CutsOr<CUT1,CUT2>
  87.   >::type
  88. operator || (const CUT1& a, const CUT2& b) {
  89.   return CutsOr<CUT1,CUT2>(a,b);
  90. }
  91.  
  92. template <typename CUT>
  93. typename boost::enable_if_c<
  94.   boost::is_base_of<Cut, CUT>::value,
  95.   CutInvert<CUT>
  96.   >::type
  97. operator ! (const CUT& c) {
  98.   return CutInvert<CUT>(c);
  99. }
  100.  
  101.  
  102. //////////////////////////////////////////
  103.  
  104.  
  105. int main() {
  106.   const Cut& c1 = CutsAnd<Odd,Less>(Odd(), Less(5));
  107.   const auto c2 = Odd() && Less(5);
  108.   const auto c3 = c2 || Even();
  109.   const auto c4 = (Odd() && Less(5)) || Even();
  110.   const auto c5 = !( (Odd() && Less(5)) || Even() );
  111.   for (int i = 0; i < 10; ++i) {
  112.     cout << i << " ";
  113.     cout << ((c1.cut(i)) ? "X" : " ");
  114.     cout << ((c2.cut(i)) ? "X" : " ");
  115.     cout << ((c3.cut(i)) ? "X" : " ");
  116.     cout << ((c4.cut(i)) ? "X" : " ");
  117.     cout << ((c5.cut(i)) ? "X" : " ");
  118.     cout << endl;
  119.   }
  120.   return 0;
  121. }
  122.  
  123. // Output:
  124. // andy@duality:~/.../cxxdev/logic$ g++ logic.cc -o logic -std=c++11
  125. // andy@duality:~/.../cxxdev/logic$ ./logic
  126. // 0   XX
  127. // 1 XXXX
  128. // 2   XX
  129. // 3 XXXX
  130. // 4   XX
  131. // 5     X
  132. // 6   XX
  133. // 7     X
  134. // 8   XX
  135. // 9     X
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement