bool to QByteArray implicit conversion curiosity?
-
Today, while fixing standards conformance issues using VS2019's
/permissive-
option and Qt 5.15.1, I 'discovered' the following (when compiling without the/permissive-
flag):The initialization
QByteArray baTrue = true;
gives the compiler error
error C2440: 'initializing': cannot convert from 'bool' to 'QByteArray' message : No constructor could take the source type, or constructor overload resolution was ambiguous
However, the following seems to pass:
QByteArray baFalse = false;
with the following Google Test assertions holding
ASSERT_TRUE(baFalse.isEmpty()); ASSERT_TRUE(baFalse.isNull()); ASSERT_NE(baFalse, QByteArray("0"));
What the hell is happening here???
-
@Bart_Vandewoestyne
In mygcc
/clang
, the statementQByteArray baFalse = false;
generates the same "no viable conversion" error asQByteArray baTrue = true;
does.I can't help what your MSVC might or might not do about this. At a guess it treats it as a match against the QByteArray::QByteArray(const char *data, int size = -1) overload:
Constructs a byte array containing the first size bytes of array data.
If data is 0, a null byte array is constructed.
I am guessing that
false
is getting coerced to C++0
/nullptr
in your compiler? -
@JonB said in bool to QByteArray implicit conversion curiosity?:
I am guessing that
false
is getting coerced to C++0
/nullptr
in your compiler?Yep, it sure looks like that. However, at https://stackoverflow.com/questions/37214420/conversion-of-false-to-object-via-const-char-constructor I find that in C++14, also the
false
case should not pass (which is probably why you also got an error forfalse
with your version of gcc/clang). However, for as far as I can see, I am using C++14 (which is the default in VS2019 apparently):Not completely sure why my
false
case then passes to be honest... -
Maybe a compiler bug/quirk. You can try it out with a simple class with this ctor
class Foo { Foo(const char *); }
-
@Christian-Ehrlicher said in bool to QByteArray implicit conversion curiosity?:
Maybe a compiler bug/quirk. You can try it out with a simple class with this ctor
class Foo { Foo(const char *); }
OK, so here's the program I used to test:
struct Foo { Foo(const char*) {} }; int main() { Foo f = false; }
First, I test with the following g++ version under Cygwin:
$ g++ --version | head -1 g++.exe (x86_64-posix-seh, Built by strawberryperl.com project) 8.3.0
C++98 compilation output only gives a warning, but compiles:
$ g++ -std=c++98 bool_to_type_implicit_conversion.cpp bool_to_type_implicit_conversion.cpp: In function 'int main()': bool_to_type_implicit_conversion.cpp:7:13: warning: converting 'false' to pointer type for argument 1 of 'Foo::Foo(const char*)' [-Wconversion-null] Foo f = false; ^~~~~
C++11 and C++14 compilation output gives an error:
$ g++ -std=c++11 bool_to_type_implicit_conversion.cpp bool_to_type_implicit_conversion.cpp: In function 'int main()': bool_to_type_implicit_conversion.cpp:7:13: error: conversion from 'bool' to non-scalar type 'Foo' requested Foo f = false; ^~~~~ $ g++ -std=c++14 bool_to_type_implicit_conversion.cpp bool_to_type_implicit_conversion.cpp: In function 'int main()': bool_to_type_implicit_conversion.cpp:7:13: error: conversion from 'bool' to non-scalar type 'Foo' requested Foo f = false; ^~~~~
Using the Visual Studio 2019 compiler in C++14 and C++17 does not give an error:
D:\GIT\Cpp\tests>cl /std:c++14 bool_to_type_implicit_conversion.cpp Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29335 for x86 Copyright (C) Microsoft Corporation. All rights reserved. bool_to_type_implicit_conversion.cpp Microsoft (R) Incremental Linker Version 14.28.29335.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:bool_to_type_implicit_conversion.exe bool_to_type_implicit_conversion.obj D:\GIT\Cpp\tests>cl /std:c++17 bool_to_type_implicit_conversion.cpp Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29335 for x86 Copyright (C) Microsoft Corporation. All rights reserved. bool_to_type_implicit_conversion.cpp Microsoft (R) Incremental Linker Version 14.28.29335.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:bool_to_type_implicit_conversion.exe bool_to_type_implicit_conversion.obj
Using the Visual Studio 2019 compiler in 'c++latest' mode does give an error:
D:\GIT\Cpp\tests>cl /std:c++latest bool_to_type_implicit_conversion.cpp Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29335 for x86 Copyright (C) Microsoft Corporation. All rights reserved. /std:c++latest is provided as a preview of language features from the latest C++ working draft, and we're eager to hear about bugs and suggestions for improvements. However, note that these features are provided as-is without support, and subject to changes or removal as the working draft evolves. See https://go.microsoft.com/fwlink/?linkid=2045807 for details. bool_to_type_implicit_conversion.cpp bool_to_type_implicit_conversion.cpp(7): error C2440: 'initializing': cannot convert from 'bool' to 'Foo' bool_to_type_implicit_conversion.cpp(7): note: No constructor could take the source type, or constructor overload resolution was ambiguous
I'm not sure what the correct behavior for C++11, C++14, C++17 or 'c++latest' should be, but clearly there is a difference in behavior between g++ and the cl compiler for C++14...
-
I would say MSVC is wrong. nullptr and false are two different values which should not be castable to each other.
-
@Bart_Vandewoestyne , @Christian-Ehrlicher
The specifically MSVC issue seems to be https://developercommunity.visualstudio.com/content/problem/47568/false-to-pointer-implicit-conversion.htmlwith Mr Microsoft seemingly only addressing this in August 2019 (my bold)
Hi all, thank you for submitting the feedback. This wording was changed in a Defect Report against C++11, known as CWG 903. Since this is a breaking change, we've implemented it under our conformance mode
/permissive-
. It will be available in a future release of VS 2019--most likely VS 2019 16.4 Preview 1. You'll get another post on this thread when the fix is available.Then back in https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160 mentioned earlier:
Implicit conversion of integral constant expressions to null pointer
The MSVC compiler now implements CWG Issue 903 in conformance mode (
/permissive-
). This rule disallows implicit conversion of integral constant expressions (except for the integer literal '0') to null pointer constants. The following example produces C2440 in conformance mode:int* f(bool* p) { p = false; // error C2440: '=': cannot convert from 'bool' to 'bool *' p = 0; // OK return false; // error C2440: 'return': cannot convert from 'bool' to 'int *' }
To fix the error, use nullptr instead of false. A literal 0 is still allowed:
int* f(bool* p) { p = nullptr; // OK p = 0; // OK return nullptr; // OK }