fork download
  1. #include <tuple>
  2.  
  3. template<class T, class Func, class BaseList> struct require_all_bases_type;
  4. template<class T, class Func, class...Bases>
  5. struct require_all_bases_type<T, Func,std::tuple<Bases...>>
  6. {
  7. require_all_bases_type(Func f=Func{}) :f(std::move(f)) {}
  8.  
  9. //binary operator
  10. bool operator()(const T& left, const T& right)
  11. {return execute<Bases...>(left, right, std::integral_constant<bool,(sizeof...(Bases)>1)>{});}
  12. //unary operator
  13. bool operator()(const T& left)
  14. {return execute<Bases...>(left);}
  15. private:
  16. //binary expander
  17. template<class CurBase, class...Rest> bool execute(const T& left, const T& right, std::true_type)
  18. {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right)) && execute<Rest...>(left, right, std::integral_constant<bool,(sizeof...(Rest)>1)>{});}
  19. //binary end-case
  20. template<class CurBase> bool execute(const T& left, const T& right, std::false_type)
  21. {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right));}
  22. //unary expander
  23. template<class CurBase, class...Rest> bool execute(const T& left, std::true_type)
  24. {return f(static_cast<const CurBase&>(left)) && execute<Rest...>(left, std::integral_constant<bool,(sizeof...(Rest)>1)>{});}
  25. //unary end-case
  26. template<class CurBase> bool execute(const T& left, std::false_type)
  27. {return f(static_cast<const CurBase&>(left));}
  28.  
  29. Func f;
  30. };
  31. template<class BaseList, class T, class Func>
  32. bool require_all_bases(const T& left, const T& right, Func f={})
  33. {return require_all_bases_type<T,Func,BaseList>(std::move(f))(left, right);}
  34.  
  35. template<class T, class Func, class BaseList> struct compare_bases_type;
  36. template<class T, class Func, class...Bases>
  37. struct compare_bases_type<T, Func, std::tuple<Bases...>>
  38. {
  39. compare_bases_type(Func f=Func{}) :f(std::move(f)) {}
  40.  
  41. bool operator()(const T& left, const T& right)
  42. {return execute<Bases...>(left, right, std::integral_constant<bool,(sizeof...(Bases)>1)>{});}
  43. private:
  44. template<class CurBase, class...Rest>
  45. bool execute(const T& left, const T& right, std::true_type)
  46. {
  47. const CurBase& l = left;
  48. const CurBase& r = right;
  49. if (!(l==r))
  50. return f(l,r);
  51. return execute<Rest...>(left, right, std::integral_constant<bool,(sizeof...(Rest)>1)>{});
  52. }
  53. template<class CurBase> bool execute(const T& left, const T& right, std::false_type)
  54. {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right));}
  55.  
  56. Func f;
  57. };
  58. template<class BaseList, class T, class Func>
  59. bool compare_bases(const T& left, const T& right, Func f={})
  60. {return compare_bases_type<T,Func,BaseList>(std::move(f))(left, right);}
  61.  
  62.  
  63.  
  64.  
  65. #include <cstdlib>
  66. #include <iostream>
  67. #include <functional>
  68.  
  69. //////////////////////////////////////////////////////////////////////////////////
  70.  
  71. struct Base1
  72. {
  73. Base1( unsigned& val ) : m_val( val ){}
  74. bool operator==( const Base1& rhs )const { return m_val == rhs.m_val; }
  75. unsigned& m_val;
  76. };
  77.  
  78. //////////////////////////////////////////////////////////////////////////////////
  79.  
  80. struct Base2
  81. {
  82. Base2( unsigned& val ) : m_val( val ){}
  83. bool operator==( const Base2& rhs ) const { return m_val == rhs.m_val; }
  84. unsigned& m_val;
  85. };
  86.  
  87. //////////////////////////////////////////////////////////////////////////////////
  88.  
  89. class Derived : public Base1 , public Base2 // Real problem has many more more Base classes
  90. {
  91. typedef std::tuple<Base1,Base2> BaseList;
  92. public:
  93. Derived( unsigned& val1 , unsigned& val2 ) : Base1( val1 ) , Base2( val2 )
  94. {
  95. }
  96.  
  97. bool operator==( const Derived& rhs ) const
  98. {return require_all_bases<BaseList>(*this,rhs,std::equal_to<void>{});}
  99. //bool operator!=( const Derived& rhs ) const
  100. //{return require_all_bases<BaseList>(*this,rhs,std::not_equal_to<void>{});}
  101. //bool operator<( const Derived& rhs ) const
  102. //{return compare_bases<BaseList>(*this,rhs,std::less<void>{});}
  103. //bool operator<=( const Derived& rhs ) const
  104. //{return compare_bases<BaseList>(*this,rhs,std::less_equal<void>{});}
  105. //bool operator>=( const Derived& rhs ) const
  106. //{return compare_bases<BaseList>(*this,rhs,std::greater_equal<void>{});}
  107. //bool operator>( const Derived& rhs ) const
  108. //{return compare_bases<BaseList>(*this,rhs,std::greater<void>{});}
  109. };
  110.  
  111. //////////////////////////////////////////////////////////////////////////////////
  112.  
  113. int main()
  114. {
  115. unsigned val1 = 42 , val2 = 24 , val3 = 0;
  116. Derived d1( val1 , val2 );
  117. Derived d2( val1 , val3 );
  118.  
  119. std::cout << ( d1 == d2 ) << std::endl;
  120. return EXIT_SUCCESS;
  121. }
  122.  
  123. //////////////////////////////////////////////////////////////////////////////////
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
In file included from /usr/include/c++/4.8/string:48:0,
                 from /usr/include/c++/4.8/stdexcept:39,
                 from /usr/include/c++/4.8/array:38,
                 from /usr/include/c++/4.8/tuple:39,
                 from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_function.h: In instantiation of ‘struct std::equal_to<void>’:
prog.cpp:98:68:   required from here
/usr/include/c++/4.8/bits/stl_function.h:207:7: error: forming reference to void
       operator()(const _Tp& __x, const _Tp& __y) const
       ^
prog.cpp: In instantiation of ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::execute(const T&, const T&, std::true_type) [with CurBase = Base1; Rest = {Base2}; T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}; std::true_type = std::integral_constant<bool, true>]’:
prog.cpp:11:20:   required from ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::operator()(const T&, const T&) [with T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}]’
prog.cpp:33:74:   required from ‘bool require_all_bases(const T&, const T&, Func) [with BaseList = std::tuple<Base1, Base2>; T = Derived; Func = std::equal_to<void>]’
prog.cpp:98:69:   required from here
prog.cpp:18:82: error: no match for call to ‘(std::equal_to<void>) (const Base1&, const Base1&)’
  {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right)) && execute<Rest...>(left, right, std::integral_constant<bool,(sizeof...(Rest)>1)>{});}
                                                                                  ^
prog.cpp: In instantiation of ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::execute(const T&, const T&, std::false_type) [with CurBase = Base2; T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}; std::false_type = std::integral_constant<bool, false>]’:
prog.cpp:18:92:   required from ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::execute(const T&, const T&, std::true_type) [with CurBase = Base1; Rest = {Base2}; T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}; std::true_type = std::integral_constant<bool, true>]’
prog.cpp:11:20:   required from ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::operator()(const T&, const T&) [with T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}]’
prog.cpp:33:74:   required from ‘bool require_all_bases(const T&, const T&, Func) [with BaseList = std::tuple<Base1, Base2>; T = Derived; Func = std::equal_to<void>]’
prog.cpp:98:69:   required from here
prog.cpp:21:80: error: no match for call to ‘(std::equal_to<void>) (const Base2&, const Base2&)’
  {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right));}
                                                                                ^
prog.cpp: In member function ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::execute(const T&, const T&, std::true_type) [with CurBase = Base1; Rest = {Base2}; T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}; std::true_type = std::integral_constant<bool, true>]’:
prog.cpp:18:167: warning: control reaches end of non-void function [-Wreturn-type]
  {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right)) && execute<Rest...>(left, right, std::integral_constant<bool,(sizeof...(Rest)>1)>{});}
                                                                                                                                                                       ^
prog.cpp: In member function ‘bool require_all_bases_type<T, Func, std::tuple<_Tail ...> >::execute(const T&, const T&, std::false_type) [with CurBase = Base2; T = Derived; Func = std::equal_to<void>; Bases = {Base1, Base2}; std::false_type = std::integral_constant<bool, false>]’:
prog.cpp:21:82: warning: control reaches end of non-void function [-Wreturn-type]
  {return f(static_cast<const CurBase&>(left),static_cast<const CurBase&>(right));}
                                                                                  ^
stdout
Standard output is empty