Is there a reason why in c++ std::string
is not implicitly converted to bool? For example
std::string s = ""
if (s) { /* s in not empty */ }
as in other languages (e.g. python). I think it is tedious to use the empty
method.
When std::string was designed, neither of these was present though. That made classes that supported conversion to bool fairly difficult to keep safe. In particular, that conversion could (and would) happen in lots of cases you almost never wanted it to.
e is implicitly convertible to T . Such expression e is said to be contextually implicitly converted to the specified type T. Note that explicit conversion functions are not considered, even though they are considered in contextual conversions to bool. (since C++11) the argument of the delete-expression ( T is any object pointer type);
(In C, it's not converted to bool, but it can still be used directly as a condition, so the effect is nearly the same.) if ("") { ... }
So when the underlying type is not implicitly convertible to bool, follow the style of surrounding code. If the value in question is a “smart pointer” like std::unique_ptr, the semantics and tradeoffs are the same. What about optional (e.g. absl::optional) values?
This probably could be added now that C++11 has added the concepts of explicit conversions and contextual conversion.
When std::string
was designed, neither of these was present though. That made classes that supported conversion to bool
fairly difficult to keep safe. In particular, that conversion could (and would) happen in lots of cases you almost never wanted it to. For example, if we assume std::string
converts to false
if empty and otherwise to true
, then you could use a string
essentially anywhere an integer or pointer was intended.
Rather than telling you about the type mismatch, the compiler would convert the string to bool, and then the bool to an integer (false -> 0, true -> 1).
Things like this happened often enough with many early attempts at string types (and there were many) that the committee apparently decided it was better to keep implicit conversions to an absolute minimum (so about the only implicit conversion supported by string
is to create a string object from a C-style string).
There were a number of methods devised for handling conversion to bool more safely. One was converting to void *
instead, which prevented some problems, but not others (this was used by iostreams). There was also a "safe bool" idiom (actually, more like a "safe bool" theme, of which there were several variations). While these certainly improved control over what conversions would and wouldn't be allowed, most of them involved a fair amount of overhead (a typical safe bool required a base class of ~50 lines of code, plus derivation from that base class, etc.)
As to how explicit conversion and contextual conversion would help, the basic idea is pretty simple. You can (starting with C++11) mark a conversion function as explicit
, which allows it to be used only where an explicit cast to the target type is used:
struct X {
explicit operator bool() { return true; }
};
int main() {
X x;
bool b1 = static_cast<bool>(x); // compiles
bool b2 = x; // won't compile
}
Contextual conversion adds a little to let the conversion to bool happen implicitly, but only in something like an if
statement, so using a class with the conversion function above, you'd get:
X x;
if (x) // allowed
int y = x; // would require explicit cast to compile
I'd add that complaints about "orthogonality" seem quite inapplicable here. Although convenient, converting a string to a Boolean doesn't really make a lot of sense. If anything, we should complain about how strange it is for string("0")
to convert to 1
(in languages where that happens).
This article mentions some reasons why operator bool()
can lead to surprising results.
Note that std::string
is just a typedef for std::basic_string<char>
. There is also std::wstring
for multi-byte characters. An implicit conversion would let you write:
std::string foo = "foo";
std::wstring bar = "bar";
if (foo == bar) {
std::cout << "This will be printed, because both are true!\n";
}
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