I goggled it & tried to find similar question on SO also but didn't find anything useful. So, posting my question here.
Consider this program:
#include <iostream>
void foo(const std::string &) {}
int main()
{
foo(false);
}
[Warning] converting 'false' to pointer type for argument 1 of 'std::basic_string::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits; _Alloc = std::allocator]' [-Wconversion-null]
Why C++ allows this without explicit cast? I was expecting to get compiler error. The program abnormally terminates at runtime due to exception displaying following:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
What the standard says about this type of implicit conversion?
Before C++11 introduced the nullptr
keyword, null pointers were a bit of a hack. Any integer literal equal to zero would suffice as a null pointer constant, and false
fit the bill.
So, the effect of your program is to construct the std::string
with a char const *
argument of NULL
. The constructor doesn't support null pointers, so you get undefined behavior.
The solution to this problem is to use a newer dialect of C++. Pass -std=c++11
to the compiler if necessary, or -std=c++14
. Then you should get something like this:
error: no matching function for call to 'foo'
http://coliru.stacked-crooked.com/a/7f3048229a1d0e5a
EDIT: Hmm, GCC doesn't appear to implement this change yet. That's a bit surprising. You might try Clang.
I've filed a bug report.
What happens is that an std::string
is implicitly constructed from false
, using the const CharT*
overload and converting false
to a null pointer. According to the documentation for that constructor :
The behavior is undefined if
s
[the pointer] does not point at an array of at leastTraits::length(s)+1
elements ofCharT
.
Hence the malfunctioning (in the form of a friendly exception, but don't rely on it).
Now, is it correct ? According to [conv.ptr] :
A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type
std::nullptr_t
.
false
has indeed a value of zero, but is not an integer literal (it's a boolean literal). The implicit conversion to the CharT*
that std::string
's constructor takes is thus non-standard.
And indeed, while GCC emits a warning, Clang refuses to compile it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With