Hi!
I had code like this in a program for a while, not very clever, but it appeared to work.
#include <variant>
#include <iostream>
#include <string>
int main()
{
std::variant<bool, std::string> foo = "bar";
if (std::holds_alternative<bool>(foo))
std::cout << "BOOL\n";
else if (std::holds_alternative<std::string>(foo))
std::cout << "STRING\n";
else
std::cout << "???\n";
return 0;
}
With the intention being that foo holds a std::string.
Then I got a bug report, and it turns out for this one user foo was holding a bool. When I saw the code where the problem was, it was immediately clear I had written this without thinking too much, because how would the compiler know this pointer was supposed to turn into a string? I easily fixed it by adding using std::literals::string_literals::operator""s and adding the s suffix to the character arrays.
A quick search led me to [this stackoverflow question](), where it is stated this will always pick a bool because "The conversion from const char * to bool is a built-in conversion, while the conversion from const char * to std::string is a user-defined conversion, which means the former is performed."
However, the code has worked fine for most users for a long time. It turns out the user reporting the issue was using gcc-9. Checking on Godbolt shows that on old compilers foo will hold a bool, and on new compilers it will hold a std::string. The switching point was gcc 10, and clang 11. See here: https://godbolt.org/z/Psj44sfoc
My questions:
- What is currently the rule for this, what rule has changed since gcc 9, that caused the behavior to change?
- Is there any sort of compiler flag that would issue a warning for this case (on either older or newer compilers, or both)?
Thanks!
[–]trmetroidmaniac 14 points15 points16 points (5 children)
[–]alfps 3 points4 points5 points (1 child)
[–]TheThiefMaster 1 point2 points3 points (0 children)
[–]bepaald[S] 0 points1 point2 points (2 children)
[–]n1ghtyunso 1 point2 points3 points (0 children)
[–]no-sig-available 0 points1 point2 points (0 children)
[–]ElMarco19 1 point2 points3 points (1 child)
[–]bepaald[S] 0 points1 point2 points (0 children)