I have this test code that I think g++ is selecting the wrong function when the second argument is a zero. If compiled with HAVE_ASCII_DEFAULT 1 it selects read(const char*, const char*) instead of read(const char*, const Variant&), for test2a/test3a. If compiled with HAVE_ASCII_DEFAULT 0 compilation fails because test2a/test3a are ambiguous. Shouldn't all of the tests select the Variant function, or am I missing something? Why do I have to explicitly create a Variant when the argument is zero?
Tested w/ g++ 3.4.3 (Mandrakelinux 10.2 3.4.3-7mdk) and 4.0.1 (self compiled) TIA, Thomas PS please CC as I'm not subscribed
#include <iostream> #include <string> #define HAVE_ASCII_DEFAULT 1 using std::string; using std::ostream; using std::cout; using std::endl; class Variant { public: enum Type { Invalid, Bool, Int, String }; Variant() : i(), b(), s(), type(Invalid) { ; } Variant(Type t) : i(), b(), s(), type(t) { ; } Variant(bool b) : i(), b(b), s(), type(Bool) { ; } Variant(int i) : i(i), b(), s(), type(Int) { ; } Variant(const string& s) : i(), b(), s(s), type(String) { ; } const char* type_name() const; friend ostream& operator<<(ostream& os, const Variant& v); private: int i; int b; string s; Type type; }; const char* Variant::type_name() const { switch(type) { case Bool: return "Bool"; case Int: return "Int"; case String: return "String"; default: break; } return "Invalid"; } ostream& operator<<(ostream& os, const Variant& v) { os << "Variant(" << v.type_name(); switch(v.type) { case Variant::Bool: os << ", " << (v.b? "true": "false"); break; case Variant::Int: os << ", " << v.i; break; case Variant::String: os << ", \"" << v.s.c_str() << '\"'; break; default: break; } return os << ')'; } class Config { public: Config() { ; } string read(const char* pKey, const string& aDefault) const; #if HAVE_ASCII_DEFAULT string read(const char* pKey, const char* aDefault) const; #endif Variant read(const char* pKey, const Variant& aDefault) const; }; #if HAVE_ASCII_DEFAULT string Config::read( const char *pKey, const char *aDefault ) const { if (!aDefault) return read(pKey, string()); return read(pKey, string(aDefault)); } #endif string Config::read( const char *pKey, const string& aDefault ) const { cout << __PRETTY_FUNCTION__ << '\t' << (pKey && *pKey? pKey: "null") << endl << "\taDefault = \"" << aDefault.c_str() << '"' << endl; return aDefault; } Variant Config::read( const char *pKey, const Variant &aDefault ) const { cout << __PRETTY_FUNCTION__ << '\t' << (pKey && *pKey? pKey: "null") << endl << "\taDefault = " << aDefault << endl; return aDefault; } int main(int, char**) { Config config; // bool config.read("test1", true); config.read("test2a", false); config.read("test2b", Variant(false)); config.read("test3a", bool()); config.read("test3b", Variant(bool())); return 0; }