Reputation: 383
I have a class which creates different kinds of variables.
And through some macro defines we want to initialize those variables.
#define NUMBER(number) JsonVariable(number)
#define STRING(text) JsonVariable(text)
#define TRUE JsonVariable(true)
#define FALSE JsonVariable(false)
Numbers are initialized fine, but Strings call the Bool constructor for unknown reasons.
JsonVariable(string x)
: type(String), s(x)
{
cout << "String" << x << endl;
sleep
}
JsonVariable(bool x)
: type(Boolean), b(x)
{
cout << "Boolean" << x << endl;
sleep
}
If I comment out the Bool constructor then the String one is called.
Any suggestions?
EDIT: This is a string constructor with the defined macros. std::string is used in the constructor.
JSON(test) = STRING("Hello")
Type is a defined enum. Also macros must be used as part of this assignment.
EDIT2: For clarification. Here's the enum type.
std::string is used with namespace std and thus single string. Also String is from the enum type so
String != string
typedef enum {
Null, Integer, Double, Boolean, String, Object, Array
} datatype;
Upvotes: 1
Views: 895
Reputation: 10880
You might experience the effect of conversion rules. If you pass a const char*
, bool
overload is preferred over std::string&
:
void f(std::string&) { std::cout << "string"; }
void f(bool) { std::cout << "bool"; }
int main() {
f("abc"); // prints 'bool'
}
This is logical: pointers are usually checked for being non-zero, thus conversion to int
/ bool
types is desirable. On the other hand, binding to a const std::string&
means a std::string
constructor and taking reference. Binding to std::string&
is impossible here as temporaries don't bind to non-const references.
Workaround is either to manually create a string or, preferably, to have a constructor for const char*
.
Upvotes: 3
Reputation: 21576
As a rule of thumb, whenever your API exposes overloaded functions or constructors of this signature (or its CV qualified and/or reference variants):
void func(std::string){}
void func(bool){}
You should always provide the one for const char*
,
void func(std::string){}
void func(bool){}
void func(const char* c){ func(std::string(c)); }
else you and your users (especially) may be in for subtle suprises because:
string-literals (e.g "abc..."
) decays quickly to const char*
and by overload resolution, conversion to bool
has a higher precedence than a user-defined conversion which is what std::string
does.
Upvotes: 2