#include #include // Minimal class path class path { public: path( const char * ) { std::cout << "path( const char * )\n"; } path( const std::string & ) { std::cout << "path( std::string & )\n"; } // for maximum efficiency, either signature must work # ifdef BY_VALUE operator const std::string() const # else operator const std::string&() const # endif { std::cout << "operator string\n"; return m_path; } #ifdef NAMED_CONVERSION std::string string() const { std::cout << "std::string string() const\n"; return m_path; } #endif private: std::string m_path; }; bool operator==( const path &, const path & ) { std::cout << "operator==( const path &, const path & )\n"; return true; } // These are the critical use cases. If any of these don't compile, usability // is unacceptably degraded. void f( const path & ) { std::cout << "f( const path & )\n"; } int main() { f( "foo" ); f( std::string( "foo" ) ); f( path( "foo" ) ); std::cout << '\n'; std::string s1( path( "foo" ) ); std::string s2 = path( "foo" ); s2 = path( "foo" ); #ifdef NAMED_CONVERSION s2 = path( "foo" ).string(); #endif std::cout << '\n'; // these must call bool path( const path &, const path & ); path( "foo" ) == path( "foo" ); path( "foo" ) == "foo"; path( "foo" ) == std::string( "foo" ); "foo" == path( "foo" ); std::string( "foo" ) == path( "foo" ); return 0; }