#include <type_traits> #include <utility> #if _MSC_VER <= 1600 //before Visual Studio 11 namespace std { template < typename T > T&& declval(); } #endif //used for SFINAE (no duck typing here) class expression_part { protected: expression_part() {} expression_part(const expression_part&) {} expression_part& operator=(const expression_part&) {return *this;} virtual ~expression_part() {} }; //used for parameter values class expression_parameter : private expression_part { public: template<class T> const T& operator()(const T& v) const {return v;} }; template<class lhsexpr> auto operator,(lhsexpr lhs, expression_parameter) -> typename std::enable_if< std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type {return std::move(lhs);} //used for constants template<class V> class expression_constant : private expression_part { V v; public: expression_constant(V v_) :v(std::move(v_)) {} template<class T> V operator()(const T&) const {return v;} }; template<class U> expression_constant<U> expr_const(U u) {return expression_constant<U>(std::move(u));} //used for addition template<class lhs, class rhs_given> class expression_add :private lhs { rhs_given rhs; public: expression_add(lhs l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {} template<class T> auto operator()(const T& v) const -> decltype(std::declval<lhs>()(v)+std::declval<rhs_given>()(v)) {return lhs::operator()(v)+rhs(v);} }; template<class lhsexpr, class rhsexpr> auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if< std::is_base_of<expression_part, lhsexpr>::value && std::is_base_of<expression_part, rhsexpr>::value, expression_add<lhsexpr, rhsexpr>>::type {return expression_add<lhsexpr, rhsexpr>(std::move(lhs), std::move(rhs));} template<class lhsexpr, class rhsexpr> auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if< std::is_base_of<expression_part, lhsexpr>::value && !std::is_base_of<expression_part, rhsexpr>::value, expression_add<lhsexpr, expression_constant<rhsexpr>>>::type {return expression_add<lhsexpr, expression_constant<rhsexpr>>(std::move(lhs), expression_constant<rhsexpr>(std::move(rhs)));} template<class lhsexpr, class rhsexpr> auto operator+(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if< !std::is_base_of<expression_part, lhsexpr>::value && std::is_base_of<expression_part, rhsexpr>::value, expression_add<expression_constant<lhsexpr>, rhsexpr>>::type {return expression_add<expression_constant<lhsexpr>, rhsexpr>(expression_constant<lhsexpr>(std::move(lhs)), std::move(rhs));} //used for multiplication template<class lhs, class rhs_given> class expression_multiply :private lhs { rhs_given rhs; public: expression_multiply(lhs l, rhs_given r):lhs(std::move(l)), rhs(std::move(r)) {} template<class T> auto operator()(const T& v) const -> decltype(std::declval<lhs>()(v)*std::declval<rhs_given>()(v)) {return lhs::operator()(v)*rhs(v);} }; template<class lhsexpr, class rhsexpr> auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if< std::is_base_of<expression_part, lhsexpr>::value && std::is_base_of<expression_part, rhsexpr>::value, expression_multiply<lhsexpr, rhsexpr>>::type {return expression_multiply<lhsexpr, rhsexpr>(std::move(lhs), std::move(rhs));} template<class lhsexpr, class rhsexpr> auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if< std::is_base_of<expression_part, lhsexpr>::value && !std::is_base_of<expression_part, rhsexpr>::value, expression_multiply<lhsexpr, expression_constant<rhsexpr>>>::type {return expression_multiply<lhsexpr, expression_constant<rhsexpr>>(std::move(lhs), expression_constant<rhsexpr>(std::move(rhs)));} template<class lhsexpr, class rhsexpr> auto operator*(lhsexpr lhs, rhsexpr rhs) -> typename std::enable_if< !std::is_base_of<expression_part, lhsexpr>::value && std::is_base_of<expression_part, rhsexpr>::value, expression_multiply<expression_constant<lhsexpr>, rhsexpr>>::type {return expression_multiply<expression_constant<lhsexpr>, rhsexpr>(expression_constant<lhsexpr>(std::move(lhs)), std::move(rhs));} template<class lhsexpr, class container> typename std::enable_if<std::is_base_of<expression_part, lhsexpr>::value, lhsexpr>::type operator>>=(lhsexpr lhs, container& rhs) { for(auto it=rhs.begin(); it!=rhs.end(); ++it) *it = lhs(*it); return lhs; } #include <vector> #include <iostream> #define take #define with , #define in >>= int main() { expression_parameter x; auto expr0 = x; auto expr1 = x*x; auto expr2 = x+x; int res = x(3); res = expr0(3); res = expr1(3); res = expr2(3); std::vector<int> container0; container0.push_back(-4); container0.push_back(0); container0.push_back(3); take x*x with x in container0; //here's the magic line for(auto it=container0.begin(); it!=container0.end(); ++it) std::cout << *it << ' '; std::cout << '\n'; std::vector<double> container1; container1.push_back(-4.4); container1.push_back(0); container1.push_back(3.3); take 1+x with x in container1; //here's the magic line for(auto it=container1.begin(); it!=container1.end(); ++it) std::cout << *it << ' '; std::cout << '\n'; auto a = x+x*x+'a'*x; auto b = a; //make sure copies work b in container0; b in container1; std::cout << sizeof(b); return 0; }
Standard input is empty
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&)'
Standard output is empty