fork download
  1. #include <type_traits>
  2. #include <utility>
  3.  
  4. #if _MSC_VER <= 1600 //before Visual Studio 11
  5. namespace std {
  6. template < typename T > T&& declval();
  7. }
  8. #endif
  9.  
  10. //used for SFINAE (no duck typing here)
  11. class expression_part {
  12. protected:
  13. expression_part() {}
  14. expression_part(const expression_part&) {}
  15. expression_part& operator=(const expression_part&) {return *this;}
  16. virtual ~expression_part() {}
  17. };
  18. //used for parameter values
  19. class expression_parameter : private expression_part {
  20. public:
  21. template<class T>
  22. const T& operator()(const T& v) const {return v;}
  23. };
  24. template<class lhsexpr>
  25. auto operator,(lhsexpr lhs, expression_parameter) -> typename std::enable_if<
  26. std::is_base_of<expression_part, lhsexpr>::value,
  27. lhsexpr>::type
  28. {return std::move(lhs);}
  29. //used for constants
  30. template<class V>
  31. class expression_constant : private expression_part {
  32. V v;
  33. public:
  34. expression_constant(V v_) :v(std::move(v_)) {}
  35. template<class T>
  36. V operator()(const T&) const {return v;}
  37. };
  38. template<class U>
  39. expression_constant<U> expr_const(U u) {return expression_constant<U>(std::move(u));}
  40. //used for addition
  41. template<class lhs, class rhs_given>
  42. class expression_add :private lhs {
  43. rhs_given rhs;
  44. public:
  45. expression_add(lhs l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {}
  46. template<class T>
  47. auto operator()(const T& v) const
  48. -> decltype(std::declval<lhs>()(v)+std::declval<rhs_given>()(v))
  49. {return lhs::operator()(v)+rhs(v);}
  50. };
  51. template<class lhsexpr, class rhsexpr>
  52. auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  53. std::is_base_of<expression_part, lhsexpr>::value &&
  54. std::is_base_of<expression_part, rhsexpr>::value,
  55. expression_add<lhsexpr, rhsexpr>>::type
  56. {return expression_add<lhsexpr, rhsexpr>(std::move(lhs), std::move(rhs));}
  57. template<class lhsexpr, class rhsexpr>
  58. auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  59. std::is_base_of<expression_part, lhsexpr>::value &&
  60. !std::is_base_of<expression_part, rhsexpr>::value,
  61. expression_add<lhsexpr, expression_constant<rhsexpr>>>::type
  62. {return expression_add<lhsexpr, expression_constant<rhsexpr>>(std::move(lhs), expression_constant<rhsexpr>(std::move(rhs)));}
  63. template<class lhsexpr, class rhsexpr>
  64. auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  65. !std::is_base_of<expression_part, lhsexpr>::value &&
  66. std::is_base_of<expression_part, rhsexpr>::value,
  67. expression_add<expression_constant<lhsexpr>, rhsexpr>>::type
  68. {return expression_add<expression_constant<lhsexpr>, rhsexpr>(expression_constant<lhsexpr>(std::move(lhs)), std::move(rhs));}
  69. //used for multiplication
  70. template<class lhs, class rhs_given>
  71. class expression_multiply :private lhs {
  72. rhs_given rhs;
  73. public:
  74. expression_multiply(lhs l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {}
  75. template<class T>
  76. auto operator()(const T& v) const
  77. -> decltype(std::declval<lhs>()(v)*std::declval<rhs_given>()(v))
  78. {return lhs::operator()(v)*rhs(v);}
  79. };
  80. template<class lhsexpr, class rhsexpr>
  81. auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  82. std::is_base_of<expression_part, lhsexpr>::value &&
  83. std::is_base_of<expression_part, rhsexpr>::value,
  84. expression_multiply<lhsexpr, rhsexpr>>::type
  85. {return expression_multiply<lhsexpr, rhsexpr>(std::move(lhs), std::move(rhs));}
  86. template<class lhsexpr, class rhsexpr>
  87. auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  88. std::is_base_of<expression_part, lhsexpr>::value &&
  89. !std::is_base_of<expression_part, rhsexpr>::value,
  90. expression_multiply<lhsexpr, expression_constant<rhsexpr>>>::type
  91. {return expression_multiply<lhsexpr, expression_constant<rhsexpr>>(std::move(lhs), expression_constant<rhsexpr>(std::move(rhs)));}
  92. template<class lhsexpr, class rhsexpr>
  93. auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  94. !std::is_base_of<expression_part, lhsexpr>::value &&
  95. std::is_base_of<expression_part, rhsexpr>::value,
  96. expression_multiply<expression_constant<lhsexpr>, rhsexpr>>::type
  97. {return expression_multiply<expression_constant<lhsexpr>, rhsexpr>(expression_constant<lhsexpr>(std::move(lhs)), std::move(rhs));}
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104. template<class lhsexpr, class container>
  105. typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type
  106. operator>>=(lhsexpr lhs, container& rhs)
  107. {
  108. for(auto it=rhs.begin(); it!=rhs.end(); ++it)
  109. *it = lhs(*it);
  110. return lhs;
  111. }
  112.  
  113. #include <vector>
  114. #include <iostream>
  115.  
  116. #define take
  117. #define with ,
  118. #define in >>=
  119.  
  120. int main() {
  121. expression_parameter x;
  122.  
  123. auto expr0 = x;
  124. auto expr1 = x*x;
  125. auto expr2 = x+x;
  126. int res = x(3);
  127. res = expr0(3);
  128. res = expr1(3);
  129. res = expr2(3);
  130.  
  131. std::vector<int> container0;
  132. container0.push_back(-4);
  133. container0.push_back(0);
  134. container0.push_back(3);
  135. take x*x with x in container0; //here's the magic line
  136. for(auto it=container0.begin(); it!=container0.end(); ++it)
  137. std::cout << *it << ' ';
  138. std::cout << '\n';
  139.  
  140. std::vector<double> container1;
  141. container1.push_back(-4.4);
  142. container1.push_back(0);
  143. container1.push_back(3.3);
  144. take 1+x with x in container1; //here's the magic line
  145. for(auto it=container1.begin(); it!=container1.end(); ++it)
  146. std::cout << *it << ' ';
  147. std::cout << '\n';
  148.  
  149. auto a = x+x*x+'a'*x;
  150. auto b = a; //make sure copies work
  151. b in container0;
  152. b in container1;
  153. std::cout << sizeof(b);
  154.  
  155. return 0;
  156. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In instantiation of 'expression_multiply<expression_parameter, expression_parameter>':
prog.cpp:124:17:   instantiated from here
prog.cpp:76:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp:76:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp: In instantiation of 'expression_add<expression_parameter, expression_parameter>':
prog.cpp:125:17:   instantiated from here
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp: In function 'int main()':
prog.cpp:128:15: error: no match for call to '(expression_multiply<expression_parameter, expression_parameter>) (int)'
prog.cpp:129:15: error: no match for call to '(expression_add<expression_parameter, expression_parameter>) (int)'
prog.cpp: At global scope:
prog.cpp: In instantiation of 'expression_add<expression_constant<int>, expression_parameter>':
prog.cpp:144:12:   instantiated from here
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp: In instantiation of 'expression_add<expression_constant<int>, expression_parameter>':
prog.cpp:144:12:   instantiated from here
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_constant<int>, typename std::add_rvalue_reference<_Tp>::type = expression_constant<int>&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_constant<int>]
prog.cpp: In instantiation of 'expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >':
prog.cpp:149:18:   instantiated from here
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_multiply<expression_parameter, expression_parameter>, typename std::add_rvalue_reference<_Tp>::type = expression_multiply<expression_parameter, expression_parameter>&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_multiply<expression_parameter, expression_parameter>]
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp: In instantiation of 'expression_multiply<expression_constant<char>, expression_parameter>':
prog.cpp:149:24:   instantiated from here
prog.cpp:76:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_parameter, typename std::add_rvalue_reference<_Tp>::type = expression_parameter&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_parameter]
prog.cpp: In instantiation of 'expression_multiply<expression_constant<char>, expression_parameter>':
prog.cpp:149:24:   instantiated from here
prog.cpp:76:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_constant<char>, typename std::add_rvalue_reference<_Tp>::type = expression_constant<char>&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_constant<char>]
prog.cpp: In instantiation of 'expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >':
prog.cpp:149:24:   instantiated from here
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_multiply<expression_constant<char>, expression_parameter>, typename std::add_rvalue_reference<_Tp>::type = expression_multiply<expression_constant<char>, expression_parameter>&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_multiply<expression_constant<char>, expression_parameter>]
prog.cpp: In instantiation of 'expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >':
prog.cpp:149:24:   instantiated from here
prog.cpp:47:10: error: call of overloaded 'declval()' is ambiguous
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/type_traits:624:13: note: candidates are: typename std::add_rvalue_reference<_Tp>::type std::declval() [with _Tp = expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, typename std::add_rvalue_reference<_Tp>::type = expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >&&]
prog.cpp:6:30: note:                 T&& std::declval() [with T = expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >]
prog.cpp: In function 'typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type operator>>=(lhsexpr, container&) [with lhsexpr = expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >, container = std::vector<int>, typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type = expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >]':
prog.cpp:151:10:   instantiated from here
prog.cpp:109:9: error: no match for call to '(expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >) (int&)'
prog.cpp: In function 'typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type operator>>=(lhsexpr, container&) [with lhsexpr = expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >, container = std::vector<double>, typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type = expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >]':
prog.cpp:152:10:   instantiated from here
prog.cpp:109:9: error: no match for call to '(expression_add<expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >, expression_multiply<expression_constant<char>, expression_parameter> >) (double&)'
stdout
Standard output is empty