#include <iostream>
#include <type_traits>

template<typename TF>
void write_debug_output( std::ostream & out, TF const& f ) {
	out << f;
}

struct tracer {
	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 const& f, TR const& ... rest ) {
		write_debug_output( out, f );
		out << " ";
		write( rest... );
	}
	template<typename TF>
	void write( TF const& f ) {
		write_debug_output( out, f );
	}
	void write() {
		//handle the empty params case
	}
};

#define TRACE(...) tracer( std::cout, __FILE__, __LINE__ ).write( __VA_ARGS__ )

struct my_object { };
void write_debug_output( std::ostream & out,  my_object const & f ) {
	out << "**Mine**";
}

int main() {
 	my_object a;
 	TRACE( 1, a, "okay" );
 	TRACE( 5.6, my_object() );
}
