#include <iostream>
#include <string>
#include <tuple>
#include <typeinfo>
template<std::size_t> struct int_{};
struct nil {};
template<typename T, class Tuple>
struct concat_tuple_type;
template< typename T
, typename T1, typename T2, typename T3
, typename T4, typename T5 >
struct concat_tuple_type< T, std::tuple<T1, T2, T3, T4, T5> >
{
typedef std::tuple<T, T1, T2, T3, T4, T5> result_type;
};
template< typename T, class Tuple>
typename concat_tuple_type<const T*,Tuple>::result_type concat_tuple(const T& obj, const Tuple& tuple)
{
typedef typename concat_tuple_type<const T*, Tuple>::result_type
result_type;
result_type result( obj, tuple);
}
////////////////////////////////////////////////////////////////////////////////
template<class Tuple>
struct expression
{
Tuple expr;
expression(const Tuple& x) : expr(x) {}
};
template<>
struct expression<nil>
{
};
template<typename T, typename Tuple>
expression< typename concat_tuple_type<const T*, Tuple>::result_type > operator<<(const expression<Tuple>& x, const T& obj)
{
typedef expression<typename concat_tuple_type<const T*, Tuple>::result_type>
result_type;
return result_type( concat_tuple(&obj, x.expr) );
}
template<typename T>
expression< std::tuple<const T*> > operator<<(const expression<nil>&, const T& obj)
{
return std::tuple<const T*>(&obj);
}
////////////////////////////////////////////////////////////////////////////////
template<typename Tuple, std::size_t I>
void print_expression(std::ostream& os, const expression<Tuple>& x, int_<I>)
{
print_expression(os, x, int_<I-1>());
os << ", " /*<< I << ": "*/ << *std::get<I>(x.expr);
}
template<typename Tuple>
void print_expression(std::ostream& os, const expression<Tuple>& x, int_<0>)
{
os /*<< "0: "*/ << *std::get<0>(x.expr);
}
template<class Tuple>
std::ostream& operator<<(std::ostream& os, const expression<Tuple>& x)
{
os << '(';
print_expression( os, x, int_<std::tuple_size<Tuple>::value-1>() );
os << ')';
return os;
}
////////////////////////////////////////////////////////////////////////////////
int main()
{
expression<nil> lhs;
auto x = lhs << 42;
//std::cout << typeid(x).name() << x << '\n';
//x << 42;
operator<< <int>(x, 42);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx0eXBlaW5mbz4KCnRlbXBsYXRlPHN0ZDo6c2l6ZV90PiBzdHJ1Y3QgaW50X3t9OwoKc3RydWN0IG5pbCB7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIGNsYXNzIFR1cGxlPgpzdHJ1Y3QgY29uY2F0X3R1cGxlX3R5cGU7Cgp0ZW1wbGF0ZTwgdHlwZW5hbWUgVAogICAgICAgICwgdHlwZW5hbWUgVDEsIHR5cGVuYW1lIFQyLCB0eXBlbmFtZSBUMwogICAgICAgICwgdHlwZW5hbWUgVDQsIHR5cGVuYW1lIFQ1ID4Kc3RydWN0IGNvbmNhdF90dXBsZV90eXBlPCBULCBzdGQ6OnR1cGxlPFQxLCBUMiwgVDMsIFQ0LCBUNT4gPgp7CiAgICB0eXBlZGVmIHN0ZDo6dHVwbGU8VCwgVDEsIFQyLCBUMywgVDQsIFQ1PiAgICAgICAgICAgICAgIHJlc3VsdF90eXBlOwp9OwoKdGVtcGxhdGU8IHR5cGVuYW1lIFQsIGNsYXNzIFR1cGxlPgp0eXBlbmFtZSBjb25jYXRfdHVwbGVfdHlwZTxjb25zdCBUKixUdXBsZT46OnJlc3VsdF90eXBlIGNvbmNhdF90dXBsZShjb25zdCBUJiBvYmosIGNvbnN0IFR1cGxlJiB0dXBsZSkKewoJdHlwZWRlZiB0eXBlbmFtZSBjb25jYXRfdHVwbGVfdHlwZTxjb25zdCBUKiwgVHVwbGU+OjpyZXN1bHRfdHlwZQoJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRfdHlwZTsKCXJlc3VsdF90eXBlIHJlc3VsdCggb2JqLCB0dXBsZSk7Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgp0ZW1wbGF0ZTxjbGFzcyBUdXBsZT4Kc3RydWN0IGV4cHJlc3Npb24KewoJVHVwbGUgZXhwcjsKCglleHByZXNzaW9uKGNvbnN0IFR1cGxlJiB4KSAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGV4cHIoeCkge30KfTsKCnRlbXBsYXRlPD4Kc3RydWN0IGV4cHJlc3Npb248bmlsPgp7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBUdXBsZT4KZXhwcmVzc2lvbjwgdHlwZW5hbWUgY29uY2F0X3R1cGxlX3R5cGU8Y29uc3QgVCosIFR1cGxlPjo6cmVzdWx0X3R5cGUgPiBvcGVyYXRvcjw8KGNvbnN0IGV4cHJlc3Npb248VHVwbGU+JiB4LCBjb25zdCBUJiBvYmopCnsKCXR5cGVkZWYgZXhwcmVzc2lvbjx0eXBlbmFtZSBjb25jYXRfdHVwbGVfdHlwZTxjb25zdCBUKiwgVHVwbGU+OjpyZXN1bHRfdHlwZT4KCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0X3R5cGU7CglyZXR1cm4gcmVzdWx0X3R5cGUoIGNvbmNhdF90dXBsZSgmb2JqLCB4LmV4cHIpICk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmV4cHJlc3Npb248IHN0ZDo6dHVwbGU8Y29uc3QgVCo+ID4gb3BlcmF0b3I8PChjb25zdCBleHByZXNzaW9uPG5pbD4mLCBjb25zdCBUJiBvYmopCnsKCXJldHVybiBzdGQ6OnR1cGxlPGNvbnN0IFQqPigmb2JqKTsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnRlbXBsYXRlPHR5cGVuYW1lIFR1cGxlLCBzdGQ6OnNpemVfdCBJPgp2b2lkIHByaW50X2V4cHJlc3Npb24oc3RkOjpvc3RyZWFtJiBvcywgY29uc3QgZXhwcmVzc2lvbjxUdXBsZT4mIHgsIGludF88ST4pCnsKCXByaW50X2V4cHJlc3Npb24ob3MsIHgsIGludF88SS0xPigpKTsKCW9zIDw8ICIsICIgLyo8PCBJIDw8ICI6ICIqLyA8PCAqc3RkOjpnZXQ8ST4oeC5leHByKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVHVwbGU+CnZvaWQgcHJpbnRfZXhwcmVzc2lvbihzdGQ6Om9zdHJlYW0mIG9zLCBjb25zdCBleHByZXNzaW9uPFR1cGxlPiYgeCwgaW50XzwwPikKewoJb3MgLyo8PCAiMDogIiovIDw8ICpzdGQ6OmdldDwwPih4LmV4cHIpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBUdXBsZT4Kc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsIGNvbnN0IGV4cHJlc3Npb248VHVwbGU+JiB4KQp7CglvcyA8PCAnKCc7CglwcmludF9leHByZXNzaW9uKCBvcywgeCwgaW50XzxzdGQ6OnR1cGxlX3NpemU8VHVwbGU+Ojp2YWx1ZS0xPigpICk7CglvcyA8PCAnKSc7CglyZXR1cm4gb3M7Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgppbnQgbWFpbigpCnsKICAgIGV4cHJlc3Npb248bmlsPiBsaHM7CgogICAgYXV0byB4ID0gbGhzIDw8IDQyOwoJLy9zdGQ6OmNvdXQgPDwgdHlwZWlkKHgpLm5hbWUoKSA8PCB4IDw8ICdcbic7CiAgICAvL3ggPDwgNDI7CglvcGVyYXRvcjw8IDxpbnQ+KHgsIDQyKTsKCiAgICByZXR1cm4gMDsKfQo=