#include #include "boost/static_assert.hpp" #include #include #include using namespace std; /// Base class for all cut functors (toy classifier of ints) struct Cut { virtual bool cut(int n) const = 0; virtual ~Cut() {} }; // Various cut functors operating on ints struct Odd : public Cut { bool cut(int n) const { return n % 2 == 1; } }; struct Even : public Cut { bool cut(int n) const { return n % 2 == 0; } }; struct Less : public Cut { Less(int n) : val(n) { } bool cut(int n) const { return n < val; } int val; }; struct LessEq : public Cut { LessEq(int n) : val(n) { } bool cut(int n) const { return n <= val; } int val; }; // AND, OR and NOT objects for combining cuts template struct CutsOr : public Cut { CutsOr(const CUT1& c1, const CUT2& c2) : cut1(c1), cut2(c2) { } bool cut(int n) const { return cut1.cut(n) || cut2.cut(n); } const CUT1 & cut1; const CUT2 & cut2; BOOST_STATIC_ASSERT((boost::is_base_of::value && boost::is_base_of::value)); }; template struct CutsAnd : public Cut { CutsAnd(const CUT1& c1, const CUT2& c2) : cut1(c1), cut2(c2) { } bool cut(int n) const { return cut1.cut(n) && cut2.cut(n); } const CUT1 & cut1; const CUT2 & cut2; BOOST_STATIC_ASSERT((boost::is_base_of::value && boost::is_base_of::value)); }; template struct CutInvert : public Cut { CutInvert(const CUT& c1) : poscut(c1) { } bool cut(int n) const { return !poscut.cut(n); } const CUT & poscut; BOOST_STATIC_ASSERT((boost::is_base_of::value)); }; // operator &&, operator ||, and operator ! overloads // // The enable_if complexity is needed to avoid too-global template type matching; // the code below is equivalent to simply // // template // CutsAnd operator && (const CUT1& a, const CUT2& b) { ... } // // template // CutsAnd operator || (const CUT1& a, const CUT2& b) { ... } // // template // CutInvert operator ! (const CUT& c) { ... } template typename boost::enable_if_c< boost::is_base_of::value && boost::is_base_of::value, CutsAnd >::type operator && (const CUT1& a, const CUT2& b) { return CutsAnd(a,b); } template typename boost::enable_if_c< boost::is_base_of::value && boost::is_base_of::value, CutsOr >::type operator || (const CUT1& a, const CUT2& b) { return CutsOr(a,b); } template typename boost::enable_if_c< boost::is_base_of::value, CutInvert >::type operator ! (const CUT& c) { return CutInvert(c); } ///// class CutHolder { public: CutHolder(const Cut & cut) : cut_(cut) {} bool apply(int n) { return cut_.cut(n); } private: const Cut & cut_; }; ////////////////////////////////////////// CutHolder makeCutHolder() { CutHolder ch = CutHolder((Odd() && Less(5)) || Even() ); return ch; } int main() { CutHolder ch = makeCutHolder(); const Cut& c1 = CutsAnd(Odd(), Less(5)); const Cut& c2 = Odd() && Less(5); const Cut& c3 = c2 || Even(); const Cut& c4 = (Odd() && Less(5)) || Even(); const Cut& c5 = !( (Odd() && Less(5)) || Even() ); for (int i = 0; i < 10; ++i) { cout << i << " "; cout << ((c1.cut(i)) ? "A" : " "); cout << ((c2.cut(i)) ? "B" : " "); cout << ((ch.apply(i)) ? "C" : " "); cout << ((c3.cut(i)) ? "D" : " "); cout << ((c4.cut(i)) ? "E" : " "); cout << ((c5.cut(i)) ? "F" : " "); cout << endl; } return 0; } // Output: // andy@duality:~/.../cxxdev/logic$ g++ logic.cc -o logic -std=c++11 // andy@duality:~/.../cxxdev/logic$ ./logic // 0 XX // 1 XXXX // 2 XX // 3 XXXX // 4 XX // 5 X // 6 XX // 7 X // 8 XX // 9 X