72 Advanced The Hundred
The String That Became true
one overload too many, and your error message vanishes
#include <iostream>
#include <string>
void log(const std::string& msg) { std::cout << "message: " << msg << '\n'; }
void log(bool verbose) { std::cout << "verbose mode: " << std::boolalpha << verbose << '\n'; }
int main() { log("error: disk full"); }
Run it. What does it print?
Answer
verbose mode: true — the string literal picks the bool overload, and the message is gone.
Why¶
A string literal is a const char[N] that decays to const char*, and pointer → bool is a
standard conversion (any non-null pointer is true). const char* → std::string goes
through a constructor, making it a user-defined conversion — and overload resolution ranks
any standard conversion above any user-defined one, always. How lossy the conversion looks
never enters into it. Adding a std::string_view overload does not rescue you: that is a
user-defined conversion too, so bool still wins and the output is unchanged. GCC and Clang
compile all of this in silence — -Wall -Wextra has nothing to say.
The fix¶
Give literals an exact match — array-to-pointer decay ranks as an exact match, which beats
the pointer-to-bool conversion outright:
Or keep bool out of the overload set entirely: a separate set_verbose(bool) can't hijack
anything.
Takeaway: overload resolution ranks conversion kinds, not plausibility — a standard
conversion beats a user-defined one, so a literal becomes true before it becomes a
std::string.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo