This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Fwd: zero and pointer conversions in g++
- From: Thomas Braxton <brax108 at cox dot net>
- To: gcc-help at gcc dot gnu dot org
- Date: Tue, 27 Dec 2005 13:52:33 -0600
- Subject: Fwd: zero and pointer conversions in g++
I sent this to the gcc mailing list and it was pointed out that I should have
sent it here, so I am forwarding it here in hopes that someone can shed some
light on this. Is this a bug in g++ or is this behavior mandated by the
standard? Why would the conversion from bool(0) -> NULL -> string() be better
than Variant(bool)? It seems to me that the selection of which function to
use for false should be the same as for true. This also happens with int, if
the argument is not 0 it chooses the Variant function.
BTW, the code is separated for strings for a reason, this is stripped down
code from KDE and strings are possibly translated, everything else isn't,
so strings must be treated differently.
---------- Forwarded Message ----------
Subject: zero and pointer conversions in g++
Date: Monday 26 December 2005 14:04
From: Thomas Braxton <brax108@cox.net>
To: gcc@gcc.gnu.org
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;
}