Just discovered (oops!) that the so called safe bool ideom is not as safe as it appears, for example: class Testable { bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_comparisons() const {} public: explicit Testable(bool b=true):ok_(b) {} operator bool_type() const { return ok_==true ? &Testable::this_type_does_not_support_comparisons : 0; } }; Testable t(true); bool b = t; // Compiles OK - Ooops! Which is causing multiprecision to misbehave when used in conjunction with uBlas: https://svn.boost.org/trac/boost/ticket/8292#comment:2 I guess making the conversion explicit in C++11 mode would help (I still need to test that), but is there a C++03 solution? Thanks, John.
2013/3/14 John Maddock
Just discovered (oops!) that the so called safe bool ideom is not as safe as it appears, for example:
class Testable { bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_**comparisons() const {} public: explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const { return ok_==true ? &Testable::this_type_does_not_**support_comparisons : 0; } };
Testable t(true);
bool b = t; // Compiles OK - Ooops!
I'm curious, why is this bad? I personally hate the fact, that the above doesn't compile for explicit operator bool(), which leads to idioms like !!t. Regards, Kris Which is causing multiprecision to misbehave when used in conjunction with
uBlas: https://svn.boost.org/trac/**boost/ticket/8292#comment:2https://svn.boost.org/trac/boost/ticket/8292#comment:2
I guess making the conversion explicit in C++11 mode would help (I still need to test that), but is there a C++03 solution?
Thanks, John.
class Testable { bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_**comparisons() const {} public: explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const { return ok_==true ? &Testable::this_type_does_not_**support_comparisons : 0; } };
Testable t(true);
bool b = t; // Compiles OK - Ooops!
I'm curious, why is this bad? I personally hate the fact, that the above doesn't compile for explicit operator bool(), which leads to idioms like !!t.
It's bad because the type isn't logically convertible to bool, BTW the !!t idiom isn't required in C++11 mode, the following works just fine: #include <iostream> class Testable { bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_comparisons() const {} public: explicit Testable(bool b=true):ok_(b) {} explicit operator bool() const { return ok_; } }; int main() { Testable t(true); if(t) std::cout << "Yeh\n"; if(!t) std::cout << "Oh\n"; bool b = t ? true : false; return 0; } John.
2013/3/14 John Maddock
class Testable
{ bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_****comparisons() const {}
public: explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const { return ok_==true ? &Testable::this_type_does_not_****support_comparisons : 0;
} };
Testable t(true);
bool b = t; // Compiles OK - Ooops!
I'm curious, why is this bad? I personally hate the fact, that the above doesn't compile for explicit operator bool(), which leads to idioms like !!t.
It's bad because the type isn't logically convertible to bool, BTW the !!t idiom isn't required in C++11 mode, the following works just fine:
#include <iostream>
class Testable { bool ok_; typedef void (Testable::*bool_type)() const; void this_type_does_not_support_**comparisons() const {} public: explicit Testable(bool b=true):ok_(b) {}
explicit operator bool() const { return ok_; } };
int main() { Testable t(true);
if(t) std::cout << "Yeh\n";
if(!t) std::cout << "Oh\n";
bool b = t ? true : false;
return 0;
}
bool do_something_with_a_Testable() { Testable t; [...] // return t; doesn't work return !!t; } So bool b = t; // I wish it worked with Testable::explicit operator bool, but doesn't. And the explicitness of operator bool should block situations, where bool is treated as an arithmetic type, like: t + 1 which compiles if Testable provides an implicit conversion to bool. John Maddock wrote:
It's not directly connected - except that what should have failed to compile - a function that looks like:
bool functor(number const& a, number const& b) { return a - b; }
However, I now see why allowing
bool b = t
can do harm, as in your example above.
2013/3/14 Peter Dimov
I see; yes, this is something that works with "safe bool" and has been explicitly disallowed for the new explicit operator bool.
Too bad, IMHO. Regards, Kris
bool do_something_with_a_Testable() { Testable t; [...] // return t; doesn't work return !!t; }
That's the whole point: the convertion is explicit so you can't "return t" and expect an implicit conversion, you need a static_cast if that's what you *really* want to do: bool do_something_with_a_Testable() { Testable t; [...] return static_cast<bool>(t); } Which IMO much better expresses what you're trying to do anyway, John.
2013/7/28 Ahmed Charles
So bool b = t; // I wish it worked with Testable::explicit operator bool, but doesn't.
Sorry for bringing up such an old thread, but what's wrong with writing:
bool b(t);
Which does the same thing?
Obviously needing to fix old code, that uses the former syntax ;-) And by the way, the use case I'll miss the most is: bool f() { shared_ptr<T> p = something(); some_other_things(); return p; } The last line will need to be changed somethink like: return !!p; It's no big deal, but I'll personally miss the old syntax ;-) Regards, Kris
John Maddock wrote:
Testable t(true);
bool b = t; // Compiles OK - Ooops!
Which is causing multiprecision to misbehave when used in conjunction with uBlas: https://svn.boost.org/trac/boost/ticket/8292#comment:2
Could you perhaps go into more detail? I don't see the connection between the two.
Testable t(true);
bool b = t; // Compiles OK - Ooops!
Which is causing multiprecision to misbehave when used in conjunction with uBlas: https://svn.boost.org/trac/boost/ticket/8292#comment:2
Could you perhaps go into more detail? I don't see the connection between the two.
It's not directly connected - except that what should have failed to compile - a function that looks like: bool functor(number const& a, number const& b) { return a - b; } instead compiled but does enirely the wrong thing (the bool return is a result of a "poor man's typeof" emulation which also does the wrong thing with multiprecision types - I'll fix that shortly). John.
John Maddock wrote:
It's not directly connected - except that what should have failed to compile - a function that looks like:
bool functor(number const& a, number const& b) { return a - b; }
I see; yes, this is something that works with "safe bool" and has been explicitly disallowed for the new explicit operator bool.
participants (4)
-
Ahmed Charles
-
John Maddock
-
Krzysztof Czainski
-
Peter Dimov