#include <iostream>
#include <type_traits>
template < typename TF, typename Tag>
void write_debug_output( std:: ostream & out, TF&& f, Tag ) {
out << f;
}
struct tracer {
template < typename T>
struct tag { struct type { } ; } ;
std:: ostream & out;
tracer( std:: ostream & out, char const * file, int line )
: out( out ) {
out << file << ":" << line << ": " ;
}
~tracer( ) {
out << std:: endl ;
}
template < typename TF, typename ... TR >
void write( TF&& f, TR&& ... rest ) {
typename tag<
typename std:: remove_cv <
typename std:: remove_reference < TF> :: type
> :: type
> :: type t;
write_debug_output( out, std:: forward < TF> ( f) , t ) ;
out << " " ;
write( std:: forward < TR> ( rest) ... ) ;
}
template < typename TF>
void write( TF&& f ) {
typename tag<
typename std:: remove_cv <
typename std:: remove_reference < TF> :: type
> :: type
> :: type t;
write_debug_output( out, std:: forward < TF> ( f) , t ) ;
}
void write( ) {
//handle the empty params case
}
} ;
#define TRACE(...) tracer( std::cout, __FILE__, __LINE__ ).write( __VA_ARGS__ )
#define TRACE_OUTPUT(match_type) \
template<typename TF> \
void write_debug_output( std::ostream & out, TF && f, tracer::tag<match_type>::type )
struct my_object { } ;
TRACE_OUTPUT( my_object) {
out << "my_object f is a "
<< ( std:: is_const < typename std:: remove_reference < TF> :: type > :: value ? "const " : "" )
<< ( std:: is_lvalue_reference < TF> :: value ? "lvalue" : "rvalue" ) ;
}
struct other_object {
int val;
} ;
TRACE_OUTPUT( other_object) {
out << "val=" << f.val ;
}
int main( )
{
my_object const a;
TRACE( a) ;
TRACE( "CONST" ,a) ;
my_object b;
TRACE( "MUTABLE" ,b) ;
TRACE( "RVALUE" , my_object( ) ) ;
TRACE( 123 , 5.5 ) ;
TRACE( ) ;
TRACE( "other" , other_object{ 14 } ) ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBURiwgdHlwZW5hbWUgVGFnPgp2b2lkIHdyaXRlX2RlYnVnX291dHB1dCggc3RkOjpvc3RyZWFtICYgb3V0LCBURiYmIGYsIFRhZyApIHsKCW91dCA8PCBmOwp9CgpzdHJ1Y3QgdHJhY2VyIHsKCXRlbXBsYXRlPHR5cGVuYW1lIFQ+CglzdHJ1Y3QgdGFnIHsgc3RydWN0IHR5cGUge307IH07CgkKCXN0ZDo6b3N0cmVhbSAmIG91dDsKCXRyYWNlciggc3RkOjpvc3RyZWFtICYgb3V0LCBjaGFyIGNvbnN0ICogZmlsZSwgaW50IGxpbmUgKQoJCTogb3V0KCBvdXQgKSB7CgkJb3V0IDw8IGZpbGUgPDwgIjoiIDw8IGxpbmUgPDwgIjogIjsKCX0KCX50cmFjZXIoKSB7CgkJb3V0IDw8IHN0ZDo6ZW5kbDsKCX0KCQoJdGVtcGxhdGU8dHlwZW5hbWUgVEYsIHR5cGVuYW1lIC4uLiBUUj4KCXZvaWQgd3JpdGUoIFRGJiYgZiwgVFImJiAuLi4gcmVzdCApIHsKCQl0eXBlbmFtZSB0YWc8CgkJCXR5cGVuYW1lIHN0ZDo6cmVtb3ZlX2N2PAoJCQkJdHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPFRGPjo6dHlwZQoJCQkJPjo6dHlwZQoJCQk+Ojp0eXBlIHQ7CgkJd3JpdGVfZGVidWdfb3V0cHV0KCBvdXQsIHN0ZDo6Zm9yd2FyZDxURj4oZiksIHQgKTsKCQlvdXQgPDwgIiAiOwoJCXdyaXRlKCBzdGQ6OmZvcndhcmQ8VFI+KHJlc3QpLi4uICk7Cgl9Cgl0ZW1wbGF0ZTx0eXBlbmFtZSBURj4KCXZvaWQgd3JpdGUoIFRGJiYgZiApIHsKCQl0eXBlbmFtZSB0YWc8CgkJCXR5cGVuYW1lIHN0ZDo6cmVtb3ZlX2N2PAoJCQkJdHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPFRGPjo6dHlwZQoJCQkJPjo6dHlwZQoJCQk+Ojp0eXBlIHQ7CgkJd3JpdGVfZGVidWdfb3V0cHV0KCBvdXQsIHN0ZDo6Zm9yd2FyZDxURj4oZiksIHQgKTsKCX0KCXZvaWQgd3JpdGUoKSB7CgkJLy9oYW5kbGUgdGhlIGVtcHR5IHBhcmFtcyBjYXNlCgl9Cn07CgojZGVmaW5lIFRSQUNFKC4uLikgdHJhY2VyKCBzdGQ6OmNvdXQsIF9fRklMRV9fLCBfX0xJTkVfXyApLndyaXRlKCBfX1ZBX0FSR1NfXyApCgojZGVmaW5lIFRSQUNFX09VVFBVVChtYXRjaF90eXBlKSBcCgl0ZW1wbGF0ZTx0eXBlbmFtZSBURj4gXAoJdm9pZCB3cml0ZV9kZWJ1Z19vdXRwdXQoIHN0ZDo6b3N0cmVhbSAmIG91dCwgVEYgJiYgZiwgdHJhY2VyOjp0YWc8bWF0Y2hfdHlwZT46OnR5cGUgKQoKc3RydWN0IG15X29iamVjdCB7IH07ClRSQUNFX09VVFBVVChteV9vYmplY3QpIHsKCW91dCA8PCAibXlfb2JqZWN0IGYgaXMgYSAiIAogCQk8PCAoc3RkOjppc19jb25zdDx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8VEY+Ojp0eXBlPjo6dmFsdWUgPyAiY29uc3QgIiA6ICIiICkKIAkJPDwgKHN0ZDo6aXNfbHZhbHVlX3JlZmVyZW5jZTxURj46OnZhbHVlID8gImx2YWx1ZSIgOiAicnZhbHVlIik7Cn0KCnN0cnVjdCBvdGhlcl9vYmplY3QgewoJaW50IHZhbDsKfTsKVFJBQ0VfT1VUUFVUKG90aGVyX29iamVjdCkgewogCW91dCA8PCAidmFsPSIgPDwgZi52YWw7Cn0KCmludCBtYWluKCkKewogCW15X29iamVjdCBjb25zdCBhOwoJVFJBQ0UoYSk7CiAJVFJBQ0UoIkNPTlNUIixhKTsKICAJbXlfb2JqZWN0IGI7CiAgCVRSQUNFKCJNVVRBQkxFIixiKTsKIAlUUkFDRSgiUlZBTFVFIiwgbXlfb2JqZWN0KCkgKTsKIAlUUkFDRSggMTIzLCA1LjUgKTsKIAlUUkFDRSgpOwogCVRSQUNFKCAib3RoZXIiLCBvdGhlcl9vYmplY3R7MTR9ICk7Cn0K