Why Does the Compiler Choose Bool Over String for Implicit Typecast of L""

Why does the compiler choose bool over string for implicit typecast of L?

First, the cause of this issue: C++ Standard [over.ics.rank]/2.11 defines an order for conversion sequences. It says that a user defined conversion sequence is worse than a standard conversion sequence. What happens in your case is that the string literal undergoes a boolean-conversion (defined at 4.12. This is a standard conversion). It does not use the user defined conversion to std::wstring which would be needed if it took the other overload.

I would recommend to simply change the name of one of the overloads or adding an overload that accepts the string literal directly (using parameter type wchar_t const*).


1)

When comparing the basic forms of implicit conversion sequences (as defined in [over.best.ics])

(2.1) a standard conversion sequence is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and

(2.2) a user-defined conversion sequence is a better conversion sequence than an ellipsis conversion sequence.

Why is there an implicit type conversion from pointers to bool in C++?

It's very common in C to write this

void f(T* ptr) {
if (ptr) {
// ptr is not NULL
}
}

You should make a const char* constructor.

C++: avoid automatic conversion of string to bool in overloads

You could add an template overload that takes a reference to array of char of size N where N is a template parameter, and/or one that accepts a const char*.

template <std::size_t N>
static void printValue(sts::ostringstream& out, const char (&str)[N])
{
out << str;
}

How to prevent implicit conversion from char array to bool

You can declare a function that takes const char* and don't provide a definition:

void setBar(const char*);

This will make it fail at link time. You're still left will all other implicit conversion, though - from any pointer to bool, integral to bool, floats to bool...

Another option:

struct Foo {
void setBar(bool bar_) {}
private:
template<typename T>
void setBar(T bar) {}
};

This way you'll get an error about it being private if you call it with anything else than bool.

Implicitly casting to bool?

You need to be explicit about the argument to the constructor:

JsonValue stringItem(std::string("test"));

What is happening is that you are getting an implicit conversion from const char* to bool, because this is a conversion between built-in types, and a better match than the conversion from const char* to std::string, which is a conversion involving a built-in type.

Alternatively, you can add a constructor that takes const char* and stores a string internally. This is a better option because it avoids the easy to make error you encountered:

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

Note that on the surface these seems to be no reason to store a dynamically allocated string. This probably adds unnecessary complications.

How does the compiler makes this conversion implicitly?

It's implicitly converting from unique_ptr to bool, and then from bool to int to do the multiplication.

(bool to int means true is 1 and false is 0)

What is the performance implication of converting to bool in C++?

I was puzzled by this behaviour, until I found this link:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633

Apparently, coming from the Microsoft Developer who "owns" this warning:

This warning is surprisingly
helpful, and found a bug in my code
just yesterday. I think Martin is
taking "performance warning" out of
context.

It's not about the generated code,
it's about whether or not the
programmer has signalled an intent to
change a value from int to bool
.
There is a penalty for that, and the
user has the choice to use "int"
instead of "bool" consistently (or
more likely vice versa) to avoid the
"boolifying" codegen. [...]

It is an old warning, and may have
outlived its purpose, but it's
behaving as designed here.

So it seems to me the warning is more about style and avoiding some mistakes than anything else.

Hope this will answer your question...

:-p

Strange constructor behavior

"false" is a const char[6] which decays to const char* and pointers are implicitly convertible to bool. That's why the compiler can call your constructor taking a int and a bool, since the compiler is allowed to perform one implicit conversion to make a function argument match.



Related Topics



Leave a reply



Submit