#include <iostream>
#define MAKE_OPERATOR(name, op) \
template <typename Lhs, typename Rhs> \
struct name##_ { \
Lhs lhs; Rhs rhs; \
friend std::ostream& operator<<(std::ostream& os, name##_ const& n) \
{ return os << '(' << n.lhs << #op << n.rhs << ')'; } \
friend auto eval(name##_ const& n) -> decltype(eval(n.lhs) op eval(n.rhs)) \
{ return eval(n.lhs) op eval(n.rhs); } \
}; \
template <typename Lhs, typename Rhs, typename Res=name##_<Lhs,Rhs> > \
Res name(Lhs const& lhs, Rhs const& rhs) { return Res{lhs, rhs}; }
double eval(double d) { return d; }
MAKE_OPERATOR(prod, *)
MAKE_OPERATOR(sum, +)
MAKE_OPERATOR(div, /)
int main()
{
auto a = prod(sum(sum(2, 3), 1), 5);
std::cout << a << " = " << eval(a) << '\n';
auto b = div(sum(28, 2), prod(5, 2));
std::cout << b << " = " << eval(b) << '\n';
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKI2RlZmluZSBNQUtFX09QRVJBVE9SKG5hbWUsIG9wKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogIHRlbXBsYXRlIDx0eXBlbmFtZSBMaHMsIHR5cGVuYW1lIFJocz4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgc3RydWN0IG5hbWUjI18geyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIExocyBsaHM7IFJocyByaHM7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgZnJpZW5kIHN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIG9zLCBuYW1lIyNfIGNvbnN0JiBuKSBcCiAgICB7IHJldHVybiBvcyA8PCAnKCcgPDwgbi5saHMgPDwgI29wIDw8IG4ucmhzIDw8ICcpJzsgfSAgICAgICAgICAgICAgIFwKICAgIGZyaWVuZCBhdXRvIGV2YWwobmFtZSMjXyBjb25zdCYgbikgLT4gZGVjbHR5cGUoZXZhbChuLmxocykgb3AgZXZhbChuLnJocykpIFwKICAgIHsgcmV0dXJuIGV2YWwobi5saHMpIG9wIGV2YWwobi5yaHMpOyB9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogIH07ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgdGVtcGxhdGUgPHR5cGVuYW1lIExocywgdHlwZW5hbWUgUmhzLCB0eXBlbmFtZSBSZXM9bmFtZSMjXzxMaHMsUmhzPiA+IFwKICBSZXMgbmFtZShMaHMgY29uc3QmIGxocywgUmhzIGNvbnN0JiByaHMpIHsgcmV0dXJuIFJlc3tsaHMsIHJoc307IH0KCmRvdWJsZSBldmFsKGRvdWJsZSBkKSB7IHJldHVybiBkOyB9Ck1BS0VfT1BFUkFUT1IocHJvZCwgKikKTUFLRV9PUEVSQVRPUihzdW0sICArKQpNQUtFX09QRVJBVE9SKGRpdiwgIC8pCgppbnQgbWFpbigpCnsKICBhdXRvIGEgPSBwcm9kKHN1bShzdW0oMiwgMyksIDEpLCA1KTsKICBzdGQ6OmNvdXQgPDwgYSA8PCAiID0gIiA8PCBldmFsKGEpIDw8ICdcbic7CgogIGF1dG8gYiA9IGRpdihzdW0oMjgsIDIpLCBwcm9kKDUsIDIpKTsKICBzdGQ6OmNvdXQgPDwgYiA8PCAiID0gIiA8PCBldmFsKGIpIDw8ICdcbic7Cn0KCg==