#include <iostream>
#include <string>
#include <tuple>
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 Tuple, typename T>
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;
int i = 42 ;
std:: cout << ( lhs << i) << '\n ' ;
std:: cout << ( lhs << 42 ) << '\n ' ;
std:: cout << ( lhs << 42 << 42 ) << '\n ' ;
//std::cout << (lhs << 42 << 47.11) << '\n';
//std::cout << (lhs << i << 47.11 << "blah") << '\n';
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHVwbGU+Cgp0ZW1wbGF0ZTxzdGQ6OnNpemVfdD4gc3RydWN0IGludF97fTsKCnN0cnVjdCBuaWwge307Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCBjbGFzcyBUdXBsZT4Kc3RydWN0IGNvbmNhdF90dXBsZV90eXBlOwoKdGVtcGxhdGU8IHR5cGVuYW1lIFQKICAgICAgICAsIHR5cGVuYW1lIFQxLCB0eXBlbmFtZSBUMiwgdHlwZW5hbWUgVDMKICAgICAgICAsIHR5cGVuYW1lIFQ0LCB0eXBlbmFtZSBUNSA+CnN0cnVjdCBjb25jYXRfdHVwbGVfdHlwZTwgVCwgc3RkOjp0dXBsZTxUMSwgVDIsIFQzLCBUNCwgVDU+ID4KewogICAgdHlwZWRlZiBzdGQ6OnR1cGxlPFQsIFQxLCBUMiwgVDMsIFQ0LCBUNT4gICAgICAgICAgICAgICByZXN1bHRfdHlwZTsKfTsKCnRlbXBsYXRlPCB0eXBlbmFtZSBULCBjbGFzcyBUdXBsZT4KdHlwZW5hbWUgY29uY2F0X3R1cGxlX3R5cGU8Y29uc3QgVCosVHVwbGU+OjpyZXN1bHRfdHlwZSBjb25jYXRfdHVwbGUoY29uc3QgVCYgb2JqLCBjb25zdCBUdXBsZSYgdHVwbGUpCnsKCXR5cGVkZWYgdHlwZW5hbWUgY29uY2F0X3R1cGxlX3R5cGU8Y29uc3QgVCosIFR1cGxlPjo6cmVzdWx0X3R5cGUKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0X3R5cGU7CglyZXN1bHRfdHlwZSByZXN1bHQoIG9iaiwgdHVwbGUpOwp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKdGVtcGxhdGU8Y2xhc3MgVHVwbGU+CnN0cnVjdCBleHByZXNzaW9uCnsKCVR1cGxlIGV4cHI7CgoJZXhwcmVzc2lvbihjb25zdCBUdXBsZSYgeCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBleHByKHgpIHt9Cn07Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBleHByZXNzaW9uPG5pbD4Kewp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVHVwbGUsIHR5cGVuYW1lIFQ+CmV4cHJlc3Npb248IHR5cGVuYW1lIGNvbmNhdF90dXBsZV90eXBlPGNvbnN0IFQqLCBUdXBsZT46OnJlc3VsdF90eXBlID4gb3BlcmF0b3I8PChjb25zdCBleHByZXNzaW9uPFR1cGxlPiYgeCwgY29uc3QgVCYgb2JqKQp7Cgl0eXBlZGVmIGV4cHJlc3Npb248dHlwZW5hbWUgY29uY2F0X3R1cGxlX3R5cGU8Y29uc3QgVCosIFR1cGxlPjo6cmVzdWx0X3R5cGU+CgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdF90eXBlOwoJcmV0dXJuIHJlc3VsdF90eXBlKCBjb25jYXRfdHVwbGUoJm9iaiwgeC5leHByKSApOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpleHByZXNzaW9uPCBzdGQ6OnR1cGxlPGNvbnN0IFQqPiA+IG9wZXJhdG9yPDwoY29uc3QgZXhwcmVzc2lvbjxuaWw+JiwgY29uc3QgVCYgb2JqKQp7CglyZXR1cm4gc3RkOjp0dXBsZTxjb25zdCBUKj4oJm9iaik7Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgp0ZW1wbGF0ZTx0eXBlbmFtZSBUdXBsZSwgc3RkOjpzaXplX3QgST4Kdm9pZCBwcmludF9leHByZXNzaW9uKHN0ZDo6b3N0cmVhbSYgb3MsIGNvbnN0IGV4cHJlc3Npb248VHVwbGU+JiB4LCBpbnRfPEk+KQp7CglwcmludF9leHByZXNzaW9uKG9zLCB4LCBpbnRfPEktMT4oKSk7CglvcyA8PCAiLCAiIC8qPDwgSSA8PCAiOiAiKi8gPDwgKnN0ZDo6Z2V0PEk+KHguZXhwcik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFR1cGxlPgp2b2lkIHByaW50X2V4cHJlc3Npb24oc3RkOjpvc3RyZWFtJiBvcywgY29uc3QgZXhwcmVzc2lvbjxUdXBsZT4mIHgsIGludF88MD4pCnsKCW9zIC8qPDwgIjA6ICIqLyA8PCAqc3RkOjpnZXQ8MD4oeC5leHByKTsKfQoKdGVtcGxhdGU8Y2xhc3MgVHVwbGU+CnN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIG9zLCBjb25zdCBleHByZXNzaW9uPFR1cGxlPiYgeCkKewoJb3MgPDwgJygnOwoJcHJpbnRfZXhwcmVzc2lvbiggb3MsIHgsIGludF88c3RkOjp0dXBsZV9zaXplPFR1cGxlPjo6dmFsdWUtMT4oKSApOwoJb3MgPDwgJyknOwoJcmV0dXJuIG9zOwp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKaW50IG1haW4oKQp7CiAgICBleHByZXNzaW9uPG5pbD4gbGhzOwoKCWludCBpID0gNDI7CglzdGQ6OmNvdXQgPDwgKGxocyA8PCBpKSA8PCAnXG4nOwoJc3RkOjpjb3V0IDw8IChsaHMgPDwgNDIpIDw8ICdcbic7CglzdGQ6OmNvdXQgPDwgKGxocyA8PCA0MiA8PCA0MikgPDwgJ1xuJzsKCS8vc3RkOjpjb3V0IDw8IChsaHMgPDwgNDIgPDwgNDcuMTEpIDw8ICdcbic7CgkvL3N0ZDo6Y291dCA8PCAobGhzIDw8IGkgPDwgNDcuMTEgPDwgImJsYWgiKSA8PCAnXG4nOwoKICAgIHJldHVybiAwOwp9Cg==