#include using namespace std; class A { public: A(int i) { x=i; } ostream &print(ostream &os) const { return os<< "A's int=" << x; } private: int x; }; class B { public: B(int i) { x=i; } friend ostream &operator<<(ostream &,const B &b); private: int x; }; ostream &operator<<(ostream &os, const B &b) { return os << "B's int=" << b.x; } // want a general output function that will call print if it // exists as a member method and otherwise call operator<< // TMP solution hasprint::value is true iff // T has a non-static const member "print" that takes an ostream& // as an argument and returns an ostream& template struct hasprint { // a type that can only be referenced if both parameters // refer to the same type template struct type_check_eq; // a type that, // *if* &S::print has the signature // ostream & (S::*)(ostream &) const // [namely, a pointer to a const non-static member function of S // that takes a single argument of type ostream & and returns // a value of type ostream &] // *then* it is a function that takes a pointer to a type_check_eq // and returns type "char[1]" template static char (& checkprint(type_check_eq *))[1]; // *otherwise* it is function that takes anything and returns // "char[2]" template static char (& checkprint(...))[2]; // check whether checkprint(0) is of size 1 (size of a single char) static const bool value= sizeof(checkprint(0))==1; }; // In C++03, you need enable_if (either from boost or as below) // C++11 has this "built-in" // otherwise, this works in either standard /* template struct enable_if { typedef T type; }; template struct enable_if { }; */ template typename enable_if::value,ostream&>::type output(ostream &os, const T &t) { return t.print(os); } template typename enable_if::value,ostream&>::type output(ostream &os, const T &t) { return os << t; } int main(int argc, char **argv) { int i = 10; A a(20); B b(30); output(cout,i); cout << endl; output(cout,a); cout << endl; output(cout,b); cout << endl; }