fork download
  1. #include <type_traits>
  2. #include <utility>
  3.  
  4. //used for inheriting from same type twice
  5. template<class sub_expr>
  6. class inherit_again : public sub_expr {
  7. public:
  8. inherit_again(sub_expr rhs) : sub_expr(std::move(rhs)) {}
  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. ~expression_part() {}
  17. };
  18. //used for parameter values
  19. class expression_parameter : private expression_part {
  20. public:
  21. expression_parameter& operator&&(const expression_parameter&) {return *this;} //ignored
  22. expression_parameter& operator,(const expression_parameter&) {return *this;} //ignored
  23. template<class T>
  24. const T& operator()(const T& v) const {return v;}
  25. };
  26. //used for constants
  27. template<class V>
  28. class expression_constant : private expression_part {
  29. V v;
  30. public:
  31. expression_constant& operator&&(const expression_parameter&) {return *this;} //ignored
  32. expression_parameter& operator,(const expression_parameter&) {return *this;} //ignored
  33. expression_constant(V v_) :v(std::move(v_)) {}
  34. template<class T>
  35. V operator()(const T&) const {return v;}
  36. };
  37. template<class U>
  38. expression_constant<U> expr_const(U u) {return expression_constant<U>(std::move(u));}
  39. //used for addition
  40. template<class lhs, class rhs_given>
  41. class expression_add :private lhs, private inherit_again<rhs_given> {
  42. typedef inherit_again<rhs_given> rhs;
  43. public:
  44. expression_add& operator&&(const expression_parameter&) {return *this;} //ignored
  45. expression_add& operator,(const expression_parameter&) {return *this;} //ignored
  46. expression_add(lhs l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {}
  47. template<class T>
  48. auto operator()(const T& v) const -> decltype(lhs::operator()(v)+rhs::operator()(v)) {return lhs::operator()(v)+rhs::operator()(v);}
  49. };
  50. template<class lhsexpr, class rhsexpr>
  51. auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  52. std::is_base_of<expression_part, lhsexpr>::value &&
  53. std::is_base_of<expression_part, rhsexpr>::value,
  54. expression_add<lhsexpr, rhsexpr>>::type
  55. {return expression_add<lhsexpr, rhsexpr>(std::move(lhs), std::move(rhs));}
  56. template<class lhsexpr, class rhsexpr>
  57. auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  58. std::is_base_of<expression_part, lhsexpr>::value &&
  59. !std::is_base_of<expression_part, rhsexpr>::value,
  60. expression_add<lhsexpr, expression_constant<rhsexpr>>>::type
  61. {return expression_add<lhsexpr, expression_constant<rhsexpr>>(std::move(lhs), expression_constant<rhsexpr>(std::move(rhs)));}
  62. template<class lhsexpr, class rhsexpr>
  63. auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  64. !std::is_base_of<expression_part, lhsexpr>::value &&
  65. std::is_base_of<expression_part, rhsexpr>::value,
  66. expression_add<expression_constant<lhsexpr>, rhsexpr>>::type
  67. {return expression_add<expression_constant<lhsexpr>, rhsexpr>(expression_constant<lhsexpr>(std::move(lhs)), std::move(rhs));}
  68. //used for multiplication
  69. template<class lhs, class rhs_given>
  70. class expression_multiply :private lhs, private inherit_again<rhs_given> {
  71. typedef inherit_again<rhs_given> rhs;
  72. public:
  73. expression_multiply& operator&&(const expression_parameter&) {return *this;} //ignored
  74. expression_multiply& operator,(const expression_parameter&) {return *this;} //ignored
  75. expression_multiply(lhs l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {}
  76. template<class T>
  77. auto operator()(const T& v) const -> decltype(lhs::operator()(v)*rhs::operator()(v)) {return lhs::operator()(v)*rhs::operator()(v);}
  78. };
  79. template<class lhsexpr, class rhsexpr>
  80. auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  81. std::is_base_of<expression_part, lhsexpr>::value &&
  82. std::is_base_of<expression_part, rhsexpr>::value,
  83. expression_multiply<lhsexpr, rhsexpr>>::type
  84. {return expression_multiply<lhsexpr, rhsexpr>(std::move(lhs), std::move(rhs));}
  85. template<class lhsexpr, class rhsexpr>
  86. auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  87. std::is_base_of<expression_part, lhsexpr>::value &&
  88. !std::is_base_of<expression_part, rhsexpr>::value,
  89. expression_multiply<lhsexpr, expression_constant<rhsexpr>>>::type
  90. {return expression_multiply<lhsexpr, expression_constant<rhsexpr>>(std::move(lhs), expression_constant<rhsexpr>(std::move(rhs)));}
  91. template<class lhsexpr, class rhsexpr>
  92. auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if<
  93. !std::is_base_of<expression_part, lhsexpr>::value &&
  94. std::is_base_of<expression_part, rhsexpr>::value,
  95. expression_multiply<expression_constant<lhsexpr>, rhsexpr>>::type
  96. {return expression_multiply<expression_constant<lhsexpr>, rhsexpr>(expression_constant<lhsexpr>(std::move(lhs)), std::move(rhs));}
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103. template<class lhsexpr, class container>
  104. typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type
  105. operator||(lhsexpr lhs, container& rhs)
  106. {
  107. for(auto it=rhs.begin(); it!=rhs.end(); ++it)
  108. *it = lhs(*it);
  109. return lhs;
  110. }
  111. expression_parameter x;
  112.  
  113. #include <vector>
  114. #include <iostream>
  115.  
  116. #define take
  117. #define with &&
  118. #define in ||
  119.  
  120. int main() {
  121. std::vector<int> container0;
  122. container0.push_back(-4);
  123. container0.push_back(0);
  124. container0.push_back(3);
  125. take x*x with x in container0; //here's the magic line
  126. for(auto it=container0.begin(); it!=container0.end(); ++it)
  127. std::cout << *it << ' ';
  128. std::cout << '\n';
  129.  
  130. std::vector<double> container1;
  131. container1.push_back(-4.4);
  132. container1.push_back(0);
  133. container1.push_back(3.3);
  134. take 1+x with x in container1; //here's the magic line
  135. for(auto it=container1.begin(); it!=container1.end(); ++it)
  136. std::cout << *it << ' ';
  137. std::cout << '\n';
  138.  
  139. auto a = x+x*x+'a'*x;
  140. auto b = a; //make sure copies work
  141. b in container0;
  142. b in container1;
  143. std::cout << sizeof(b);
  144.  
  145. return 0;
  146. }
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:125:12:   instantiated from here
prog.cpp:70:74: warning: direct base 'expression_parameter' inaccessible in 'expression_multiply<expression_parameter, expression_parameter>' due to ambiguity
prog.cpp: In instantiation of 'expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >':
prog.cpp:139:18:   instantiated from here
prog.cpp:41:69: warning: direct base 'expression_parameter' inaccessible in 'expression_add<expression_parameter, expression_multiply<expression_parameter, expression_parameter> >' due to ambiguity
prog.cpp: In function 'typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type operator||(lhsexpr, container&) [with lhsexpr = expression_multiply<expression_parameter, expression_parameter>, container = std::vector<int>, typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type = expression_multiply<expression_parameter, expression_parameter>]':
prog.cpp:125:24:   instantiated from here
prog.cpp:108:9: error: no match for call to '(expression_multiply<expression_parameter, 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_constant<int>, expression_parameter>, container = std::vector<double>, typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type = expression_add<expression_constant<int>, expression_parameter>]':
prog.cpp:134:24:   instantiated from here
prog.cpp:108:9: error: no match for call to '(expression_add<expression_constant<int>, expression_parameter>) (double&)'
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:141:10:   instantiated from here
prog.cpp:108: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:142:10:   instantiated from here
prog.cpp:108: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