Gcc 含蓄地向布尔施压?

Gcc 含蓄地向布尔施压?,gcc,c++11,casting,implicit,Gcc,C++11,Casting,Implicit,我的代码有一个奇怪的问题,编译器似乎在隐式地将我的参数转换为另一种类型。然而,当我将构造函数标记为显式时,它似乎并没有解决这个问题 我的单元测试中有这个 JsonValue stringItem("test"); CHECK(stringItem.type() == JsonValue::Type::String); 这失败了,结果是失败的 4 == 3 这就是构造器的样子 JsonValue::JsonValue() : mType(Type::Null) { } JsonValue:

我的代码有一个奇怪的问题,编译器似乎在隐式地将我的参数转换为另一种类型。然而,当我将构造函数标记为显式时,它似乎并没有解决这个问题

我的单元测试中有这个

JsonValue stringItem("test");
CHECK(stringItem.type() == JsonValue::Type::String);
这失败了,结果是失败的

4 == 3
这就是构造器的样子

JsonValue::JsonValue()
 : mType(Type::Null) {
}

JsonValue::JsonValue(bool ab)
 : mType(Type::Boolean) {
    mData.b = ab;
}

JsonValue::JsonValue(int ai)
 : mType(Type::Int) {
    mData.i = ai;
}

JsonValue::JsonValue(std::uint32_t aui)
 : mType(Type::UnsignedInt) {
    mData.ui = aui;
}

// It should be using this constructory
// but mType is not getting set to Type::String
JsonValue::JsonValue(const std::string &astr)
 : mType(Type::String) {
    mData.str = new std::string(astr);
}
正如我前面提到的,将
JsonValue(bool)
标记为
explicit
并不能解决问题。我还使用
-Wconversion
编译,没有任何警告

枚举看起来像这样

enum Type {
            Null = 0,
            Object,
            Array,
            String,
            Boolean,
            Int,
            UnsignedInt
         };

您需要向构造函数明确说明参数:

JsonValue stringItem(std::string("test"));
发生的情况是,您得到了从
const char*
bool
的隐式转换,因为这是内置类型之间的转换,比从
const char*
std::string
的转换更匹配,后者是涉及内置类型的转换

或者,您可以添加一个构造函数,该构造函数接受
constchar*
,并在内部存储字符串。这是一个更好的选择,因为它避免了您遇到的易犯错误:

JsonValue::JsonValue(const char* astr)
 : mType(Type::String) {
    mData.str = new std::string(astr);
}

请注意,从表面上看,这些似乎不是存储动态分配字符串的理由。这可能会增加不必要的复杂性。

这有点奇怪。。您确实在标题中添加了
explicit
标记,而不是在构造函数主体中?为了更好地衡量,您是否可以发布一个完整的程序,以便我们可以原封不动地编译它?这是一个可运行的版本:我确实使用了一个名为
struct bool
的ligtweight包装器作为我的判别联合的成员。不幸的是,由于JsonValue和JsonObject/JsonArray。我把数据存储在一个union@rcapote这可能是存储
JsonArray
和/或
JsonObject
指针的原因。@Casey啊好的,谢谢你的提示。还有一件事我必须跟踪of@Casey我仔细看了一下您的示例……什么是
::new(&mData.str)std::string(astr)正在做什么?从未见过这种构造before@rcapote“placement new”-它在
&mData.str
指向的内存中构造一个
std::string
。您可以跳过基本类型的构造,因为它们是平凡的,只需分配它们,就像在其他构造函数中一样,但是
std::string
具有非平凡的构造。我本可以(也可能应该)通过以下方式达到同样的效果。