#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>
void 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+OjpyZXN1bHRfdHlwZQoJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRfdHlwZTsKCXJlc3VsdF90eXBlIHJlc3VsdCggb2JqLCB0dXBsZSk7Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgp0ZW1wbGF0ZTxjbGFzcyBUdXBsZT4Kc3RydWN0IGV4cHJlc3Npb24KewoJVHVwbGUgZXhwcjsKCglleHByZXNzaW9uKGNvbnN0IFR1cGxlJiB4KSAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGV4cHIoeCkge30KfTsKCnRlbXBsYXRlPD4Kc3RydWN0IGV4cHJlc3Npb248bmlsPgp7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBUdXBsZT4Kdm9pZCBvcGVyYXRvcjw8KGNvbnN0IGV4cHJlc3Npb248VHVwbGU+JiB4LCBjb25zdCBUJiBvYmopCnsKCXR5cGVkZWYgZXhwcmVzc2lvbjx0eXBlbmFtZSBjb25jYXRfdHVwbGVfdHlwZTxjb25zdCBUKiwgVHVwbGU+OjpyZXN1bHRfdHlwZT4KCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0X3R5cGU7CglyZXR1cm4gcmVzdWx0X3R5cGUoIGNvbmNhdF90dXBsZSgmb2JqLCB4LmV4cHIpICk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmV4cHJlc3Npb248IHN0ZDo6dHVwbGU8Y29uc3QgVCo+ID4gb3BlcmF0b3I8PChjb25zdCBleHByZXNzaW9uPG5pbD4mLCBjb25zdCBUJiBvYmopCnsKCXJldHVybiBzdGQ6OnR1cGxlPGNvbnN0IFQqPigmb2JqKTsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCnRlbXBsYXRlPHR5cGVuYW1lIFR1cGxlLCBzdGQ6OnNpemVfdCBJPgp2b2lkIHByaW50X2V4cHJlc3Npb24oc3RkOjpvc3RyZWFtJiBvcywgY29uc3QgZXhwcmVzc2lvbjxUdXBsZT4mIHgsIGludF88ST4pCnsKCXByaW50X2V4cHJlc3Npb24ob3MsIHgsIGludF88SS0xPigpKTsKCW9zIDw8ICIsICIgLyo8PCBJIDw8ICI6ICIqLyA8PCAqc3RkOjpnZXQ8ST4oeC5leHByKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVHVwbGU+CnZvaWQgcHJpbnRfZXhwcmVzc2lvbihzdGQ6Om9zdHJlYW0mIG9zLCBjb25zdCBleHByZXNzaW9uPFR1cGxlPiYgeCwgaW50XzwwPikKewoJb3MgLyo8PCAiMDogIiovIDw8ICpzdGQ6OmdldDwwPih4LmV4cHIpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBUdXBsZT4Kc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgb3MsIGNvbnN0IGV4cHJlc3Npb248VHVwbGU+JiB4KQp7CglvcyA8PCAnKCc7CglwcmludF9leHByZXNzaW9uKCBvcywgeCwgaW50XzxzdGQ6OnR1cGxlX3NpemU8VHVwbGU+Ojp2YWx1ZS0xPigpICk7CglvcyA8PCAnKSc7CglyZXR1cm4gb3M7Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCgppbnQgbWFpbigpCnsKICAgIGV4cHJlc3Npb248bmlsPiBsaHM7CgogICAgYXV0byB4ID0gbGhzIDw8IDQyOwoJLy9zdGQ6OmNvdXQgPDwgdHlwZWlkKHgpLm5hbWUoKSA8PCB4IDw8ICdcbic7CiAgICAvL3ggPDwgNDI7CglvcGVyYXRvcjw8IDxpbnQ+KHgsIDQyKTsKCiAgICByZXR1cm4gMDsKfQo=
compilation info
prog.cpp: In function 'void operator<<(const expression<Tuple>&, const T&) [with T = int, Tuple = std::tuple<const int*>]':
prog.cpp:91:24: instantiated from here
prog.cpp:48:58: error: invalid use of incomplete type 'struct concat_tuple_type<const int*, std::tuple<const int*> >'
prog.cpp:11:8: error: declaration of 'struct concat_tuple_type<const int*, std::tuple<const int*> >'
prog.cpp:49:49: error: no matching function for call to 'concat_tuple(const int*, const std::tuple<const int*>&)'
prog.cpp:49:49: error: return-statement with a value, in function returning 'void'
stdout