#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;
}