safe-bool CRTP class

Hello, Vladimir Batov prepared a safebool helper class as part of his Pimpl library. I quote his rationale: /// An implicit conversion to bool (operator bool() const) is very much /// idiomatic and is often deployed in constructs like "if (foo)" and "if (!foo)" /// (with no explicit op!() defined). However, sadly, implementing "operator bool()" /// is *wrong* as that conversion kicks in far too often and unexpectedly. Like in /// "foo == 1", "foo+1", "1+foo" or potentially during lexical_cast<string>(foo) /// (if there are no op>>() and op<<() defined). Consequently, that "implicit /// conversion to bool" functionality has to be implemented in an indirect and /// somewhat awkward way via an implicit conversion to some other type. The best /// type for the purpose appears to be a pointer to a member function. For more /// see the chapter 7.7 in Alexandrescu's "Modern C++ Design" and the article at /// http://www.artima.com/cppsource/safebool.html by Bjorn Karlsson. In the review of Pimpl Joej Falcou suggested to make safebool a CRTP base class. I had prepared such a class some time ego, and I've been using it for a while now. Is there interest in adding it to boost? Perhaps as part of the operators library? /** * CRTP class, that provides operator unspecified_bool_t() const, implemented in terms of * Derived::operator! */ template < class Derived, class Base = empty_t > class boolable : public Base { void unspecified_bool_t_f() {} typedef void (boolable::*unspecified_bool_t)(); public: operator unspecified_bool_t() const { return ! static_cast<Derived const&>( *this ) ? 0 : &boolable::unspecified_bool_t_f; } }; Usage: struct X : public boolable<X> { bool operator!() const { return condition; } // inherit operator unspecified_bool_t implemented in terms of the above operator! }; Regards, Kris

On 5/27/11 7:02 AM, Krzysztof Czainski wrote:
I had prepared such a class some time ego, and I've been using it for a while now. Is there interest in adding it to boost? Perhaps as part of the operators library?
Hmm, I like the idea of insulating the user from having to construct a fancy type to return a safe bool, but it is a little weird to have the user implement the ! operator instead of the bool operator directly. How about simply defining an as_bool method and having the user implement that: template< class Derived, class Base = empty_t> class boolable : public Base { void unspecified_bool_t_f() {} typedef void (boolable::*unspecified_bool_t)(); public: operator unspecified_bool_t() const { return static_cast<Derived const&>( *this ).as_bool() ?&boolable::unspecified_bool_t_f : 0; } bool operator!() const { return !(*this); } }; Usage: struct X : public boolable<X> { bool as_bool() const { return condition; } };

Krzysztof Czainski wrote:
Vladimir Batov prepared a safebool helper class as part of his Pimpl library.
[snip]
In the review of Pimpl Joej Falcou suggested to make safebool a CRTP base class.
I had prepared such a class some time ego, and I've been using it for a while now. Is there interest in adding it to boost? Perhaps as part of the operators library?
+1
template < class Derived, class Base = empty_t >
I like that you're allowing for a base class.
class boolable : public Base
Why not s/boolable/safe_bool/?
{ void unspecified_bool_t_f() {}
typedef void (boolable::*unspecified_bool_t)();
public:
operator unspecified_bool_t() const { return ! static_cast<Derived const&>( *this ) ? 0 : &boolable::unspecified_bool_t_f;
This doesn't support types that have no other reason to define operator !() or that have a ready-made is_valid() sort of function. IOW, the "valid" or "invalid" function on which to rely should be configurable. (It should be possible to provide either one.) I understand that you're assuming that if one can write if (x), one might assume that if (!x) should also work, but that should work anyway with the safe-bool operator, right? _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 5/27/11 9:28 AM, Stewart, Robert wrote:
template< class Derived, class Base = empty_t> I like that you're allowing for a base class.
That was my first reaction too, though the more that I have been thinking about it the more that I am having trouble thinking of an example of exactly why it is that one would ever need or want this functionality. Cheers, Greg

2011/5/27 Gregory Crosswhite <gcross@phys.washington.edu>
On 5/27/11 9:28 AM, Stewart, Robert wrote:
template< class Derived, class Base = empty_t>
I like that you're allowing for a base class.
That was my first reaction too, though the more that I have been thinking about it the more that I am having trouble thinking of an example of exactly why it is that one would ever need or want this functionality.
Cheers, Greg
That's for base class chaining to avoid multiple inheritance, just like the operators library has it. struct X : boolable<X, addable<X> > {...}; Regards, Kris Regards Kris

Krzysztof Czainski wrote:
2011/5/27 Gregory Crosswhite <gcross@phys.washington.edu>
On 5/27/11 9:28 AM, Stewart, Robert wrote:
template< class Derived, class Base = empty_t>
I like that you're allowing for a base class.
That was my first reaction too, though the more that I have been thinking about it the more that I am having trouble thinking of an example of exactly why it is that one would ever need or want this functionality.
That's for base class chaining to avoid multiple inheritance, just like the operators library has it.
struct X : boolable<X, addable<X> > {...};
It's also for cases in which one would normally have this: struct derived : base { ... }; Then, to provide safe-bool functionality for derived, one would do the following to avoid MI: struct derived : safe_bool<derived, base> { ... }; _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 5/27/11 10:08 AM, Stewart, Robert wrote:
Krzysztof Czainski wrote:
That's for base class chaining to avoid multiple inheritance, just like the operators library has it.
struct X : boolable<X, addable<X> > {...}; It's also for cases in which one would normally have this:
struct derived : base { ... };
Then, to provide safe-bool functionality for derived, one would do the following to avoid MI:
struct derived : safe_bool<derived, base> { ... };
Okay, I think I see now. It looks to me that most of the time it really wouldn't be a big deal at all to just add boolable<> (and addable<> etc.) as another base class via. multiple inheritance, but I can see how the additional flexibility is useful for times when you want to avoid multiple inheritance in order to have the clear chain of command offered by single inheritance. Thank you for the explanations! Cheers, Greg

On 27 May 2011 11:28, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Krzysztof Czainski wrote:
Vladimir Batov prepared a safebool helper class as part of his Pimpl library.
[snip]
There exists a safebool in already accepted Boost.Log: http://boost-log.svn.sourceforge.net/viewvc/boost-log/trunk/boost-log/boost/log/utility/explicit_operator_bool.hpp?revision=601&view=markup

On Fri, May 27, 2011 at 9:52 AM, Christian Holmquist <c.holmquist@gmail.com>wrote:
On 27 May 2011 11:28, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Krzysztof Czainski wrote:
Vladimir Batov prepared a safebool helper class as part of his Pimpl library.
[snip]
There exists a safebool in already accepted Boost.Log:
I'll chime in for my vote of something more along the lines of Andrey's nullary macro design, except using a pointer-to-member-variable rather than a pointer-to-member-function to address MSVC efficiency concerns (see prior post by S.T. Lavavej). I use something like the following, which I had also picked up from Andrey in a past boost-dev list post. #define BOOST_EXPLICIT_BOOL() \ private: \ struct _boost_explicit_bool_struct \ { int _dummy; int member; }; \ typedef int (_boost_explicit_bool_struct::*_boost_bool_type); \ public: \ operator _boost_bool_type() const { return !*this ? 0 : &_boost_explicit_bool_struct::member; } When BOOST_NO_EXPLICIT_CONVERSION_OPERATORS is not defined, then the above macro is defined to just declare an explicit bool conversion, so it amounts to the same framework you would use in C++0x. I prefer a macro solution over a CRTP solution because 1) it retains POD'ness (in C++03, at least; I believe the definition of POD has been extended in C++0x...?); and 2) the macro appears in the same place one would otherwise declare a bool conversion operator. I also like the solution to use operator! by default in the implementation of the explicit bool conversion operator; perhaps a second macro could be provided to allow one to specify the specific expression (e.g., "!!*this" or "as_bool()") one should use. - Jeff

On 05/27/2011 11:55 AM, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, May 27, 2011 at 9:52 AM, Christian Holmquist <c.holmquist@gmail.com>wrote:
On 27 May 2011 11:28, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Krzysztof Czainski wrote:
Vladimir Batov prepared a safebool helper class as part of his Pimpl library.
[snip]
There exists a safebool in already accepted Boost.Log:
I'll chime in for my vote of something more along the lines of Andrey's nullary macro design, except using a pointer-to-member-variable rather than a pointer-to-member-function to address MSVC efficiency concerns (see prior post by S.T. Lavavej). I use something like the following, which I had also picked up from Andrey in a past boost-dev list post.
#define BOOST_EXPLICIT_BOOL() \ private: \ struct _boost_explicit_bool_struct \ { int _dummy; int member; }; \ typedef int (_boost_explicit_bool_struct::*_boost_bool_type); \ public: \ operator _boost_bool_type() const { return !*this ? 0 : &_boost_explicit_bool_struct::member; }
When BOOST_NO_EXPLICIT_CONVERSION_OPERATORS is not defined, then the above macro is defined to just declare an explicit bool conversion, so it amounts to the same framework you would use in C++0x.
I prefer a macro solution over a CRTP solution because 1) it retains POD'ness (in C++03, at least; I believe the definition of POD has been extended in C++0x...?); and 2) the macro appears in the same place one would otherwise declare a bool conversion operator.
I also like the solution to use operator! by default in the implementation of the explicit bool conversion operator; perhaps a second macro could be provided to allow one to specify the specific expression (e.g., "!!*this" or "as_bool()") one should use.
What about a macro that can be used like BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; } In Christ, Steven Watanabe

[Steven Watanabe]
What about a macro that can be used like BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
Having done this in the STL, I can offer the following warning: you'll need to generate a different fake-bool type for every class, otherwise things will be [in]equality comparable that should not be. STL

On Fri, May 27, 2011 at 4:19 PM, Stephan T. Lavavej <stl@exchange.microsoft.com> wrote:
[Steven Watanabe]
What about a macro that can be used like BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
Having done this in the STL, I can offer the following warning: you'll need to generate a different fake-bool type for every class, otherwise things will be [in]equality comparable that should not be.
STL
ie __LINE__ and __FILE__ or __COUNTER__ etc? All the more reason for the macro, I suppose. Tony

On Sat, May 28, 2011 at 12:29 AM, Gottlob Frege <gottlobfrege@gmail.com>wrote:
ie __LINE__ and __FILE__ or __COUNTER__ etc? All the more reason for the macro, I suppose.
You can just base the type off of some nested type that's created by the macro. Also, the CRTP approach handles this fine as well (you just form the type using the child parameter). That said, I, too, have used a hand-rolled macro version in the past. Given that so many of us have done either the CRTP or macro approach at some point, something should probably make its way into boost, outside of detail. -- -Matt Calabrese

Thank you all for such large input ;-) So the way I see it, most of us agree it would be nice to see one official safe-bool implementation tool in boost. The first question is: should it be a CRTP class, or should it be a macro, or both perhaps? I suggest we talk about the name after we answer the first question ;-) And later I will try to prepare an implementation with the compiler workarounds mentioned in this thread. CRTP class usage: struct X : public convertible_to_bool<X> { bool operator!() const { return condition; } // inherit operator unspecified_bool_t implemented in terms of the above operator! }; Macro usage: BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; } I'm not sure how the macro would be implemented, but we'll get to that once we make the choice. Right now I feel convinced to the macro version. Regards Kris

On 28 May 2011, at 14:22, Krzysztof Czainski wrote:
Thank you all for such large input ;-)
So the way I see it, most of us agree it would be nice to see one official safe-bool implementation tool in boost.
The first question is: should it be a CRTP class, or should it be a macro, or both perhaps?
I think we should go macro. I wonder if the macro should take a parameter, just to give some way of getting a unique name. We could of course use some random integer / line number / file name, but such things are likely to be fragile and code could easily end up breaking the "one definition rule". Chris

On Sat, May 28, 2011 at 10:49 AM, Christopher Jefferson < chris@bubblescope.net> wrote:
I think we should go macro.
Agreed.
I wonder if the macro should take a parameter, just to give some way of getting a unique name. We could of course use some random integer / line number / file name, but such things are likely to be fragile and code could easily end up breaking the "one definition rule".
We shouldn't need to do this or use any kind of unique ID. ODR isn't a problem here, just have the macro create a nested type behind the scenes with a complicated name and use the pointer-to-member trick with that. -- -Matt Calabrese

Krzysztof Czainski wrote:
Thank you all for such large input ;-)
So the way I see it, most of us agree it would be nice to see one official safe-bool implementation tool in boost.
The first question is: should it be a CRTP class, or should it be a macro, or both perhaps?
I suggest we talk about the name after we answer the first question ;-) And later I will try to prepare an implementation with the compiler workarounds mentioned in this thread.
CRTP class usage: struct X : public convertible_to_bool<X> { bool operator!() const { return condition; } // inherit operator unspecified_bool_t implemented in terms of the above operator! };
Macro usage: BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
I'm not sure how the macro would be implemented, but we'll get to that once we make the choice.
Right now I feel convinced to the macro version.
Hi, recently we were discussion on whether we can add new classes to the boost namespace, and it seems that we shouldn't. What would be the namespace for the class or the prefix used for the macro in this case? Should this be one of the exceptions to the rule? Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/safe-bool-CRTP-class-tp3555415p3557669.ht... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Sat, May 28, 2011 at 9:22 AM, Krzysztof Czainski <1czajnik@gmail.com> wrote:
Thank you all for such large input ;-)
So the way I see it, most of us agree it would be nice to see one official safe-bool implementation tool in boost.
The first question is: should it be a CRTP class, or should it be a macro, or both perhaps?
I suggest we talk about the name after we answer the first question ;-) And later I will try to prepare an implementation with the compiler workarounds mentioned in this thread.
CRTP class usage: struct X : public convertible_to_bool<X> { bool operator!() const { return condition; } // inherit operator unspecified_bool_t implemented in terms of the above operator! };
Macro usage: BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
I'm not sure how the macro would be implemented, but we'll get to that once we make the choice.
Right now I feel convinced to the macro version.
Regards Kris
I suspect that we should offer both versions. I also think we should look back at the previous reviews and attempts at safe-bools for Boost. Although I don't think we should let the previous failed attempts discourage us. Tony

On Sat, May 28, 2011 at 9:46 AM, Gottlob Frege <gottlobfrege@gmail.com>wrote:
On Sat, May 28, 2011 at 9:22 AM, Krzysztof Czainski <1czajnik@gmail.com> wrote:
[...]
The first question is: should it be a CRTP class, or should it be a macro, or both perhaps?
[...]
I suspect that we should offer both versions.
What are the arguments for a CRTP solution over a macro solution? - Jeff

On Sat, May 28, 2011 at 3:29 PM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Sat, May 28, 2011 at 9:46 AM, Gottlob Frege <gottlobfrege@gmail.com>wrote:
On Sat, May 28, 2011 at 9:22 AM, Krzysztof Czainski <1czajnik@gmail.com> wrote:
[...]
The first question is: should it be a CRTP class, or should it be a macro, or both perhaps?
[...]
I suspect that we should offer both versions.
What are the arguments for a CRTP solution over a macro solution?
- Jeff
I hate MACROS. ie for the usual reasons that people don't like MACRO solutions - can't easily see what is really going on, harder to debug, etc. Tony

On Sat, May 28, 2011 at 3:36 PM, Gottlob Frege <gottlobfrege@gmail.com>wrote:
I hate MACROS.
ie for the usual reasons that people don't like MACRO solutions - can't easily see what is really going on, harder to debug, etc.
I don't think that would be too much of a problem in this particular case given the simplicity of the macro and the fact that it doesn't really generate code that you'd have to step through (just the code for the return type and function declaration), though I'm sure many people share your feelings. The only thing I really like about the CRTP version is that it's consistent with Boost.Operators, as was mentioned earlier. -- -Matt Calabrese

On Sat, May 28, 2011 at 4:44 PM, Matt Calabrese <rivorus@gmail.com> wrote:
I don't think that would be too much of a problem in this particular case given the simplicity of the macro and the fact that it doesn't really generate code that you'd have to step through (just the code for the return type and function declaration)
Woops, correcting myself here, it would generate a small amount of code. -- -Matt Calabrese

On Sat, May 28, 2011 at 6:22 AM, Krzysztof Czainski <1czajnik@gmail.com>wrote:
Thank you all for such large input ;-)
So the way I see it, most of us agree it would be nice to see one official safe-bool implementation tool in boost.
The first question is: should it be a CRTP class, or should it be a macro, or both perhaps?
[...]
Macro usage: BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
I'm not sure how the macro would be implemented, but we'll get to that once we make the choice.
Right now I feel convinced to the macro version.
Here's a trial attempt at an implementation of the macro (warning: not tested): #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS #define BOOST_EXPLICIT_OPERATOR_BOOL() \ explicit operator bool() #else // #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS #ifndef BOOST_NO_EXPLICIT_OPERATOR_BOOL #define BOOST_EXPLICIT_OPERATOR_BOOL() \ struct _boost_explicit_operator_bool_struct { int _dummy; int member; }; \ typedef int (_boost_explicit_operator_bool_struct::*_boost_explicit_operator_bool_type); \ operator _boost_explicit_operator_bool_type() const \ { return _boost_explicit_operator_bool_impl() ? &_boost_explicit_operator_bool_struct::member : 0; } \ bool _boost_explicit_operator_bool_impl() #else // #ifndef BOOST_NO_EXPLICIT_OPERATOR_BOOL #define BOOST_EXPLICIT_OPERATOR_BOOL() \ operator bool() #endif // #ifndef BOOST_NO_EXPLICIT_OPERATOR_BOOL #endif // #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS ...and we can, optionally, give _boost_explicit_operator_bool_struct and _boost_explicit_operator_bool_type private access, but I don't see a way to give _boost_explicit_operator_bool_impl private access, so the point might be moot. - Jeff

On Sat, May 28, 2011 at 3:23 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
Here's a trial attempt at an implementation of the macro (warning: not tested):
I haven't looked at the implementation in depth, but if I recall correctly, C++0x explicit conversions to bool are not quite the same as a safe-bool conversion (explicit conversions still generally require explicit casts, correct me if I'm wrong). Because of this, I do not believe it would be a good idea for such a macro to automatically use explicit conversion operators when available as it could result in user code that compiles in 03 but fails to compile in 0x. -- -Matt Calabrese

On Sat, May 28, 2011 at 1:31 PM, Matt Calabrese <rivorus@gmail.com> wrote:
On Sat, May 28, 2011 at 3:23 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
Here's a trial attempt at an implementation of the macro (warning: not tested):
I haven't looked at the implementation in depth, but if I recall correctly, C++0x explicit conversions to bool are not quite the same as a safe-bool conversion (explicit conversions still generally require explicit casts, correct me if I'm wrong). Because of this, I do not believe it would be a good idea for such a macro to automatically use explicit conversion operators when available as it could result in user code that compiles in 03 but fails to compile in 0x.
You make a good point, and if all C++0x compilers generate equally efficient code for each technique, then we should just stick with the slightly-more-complicated pointer-to-member hack. Perhaps it would prudent to provide a macro flag which signals to use explicit bool conversion operators when available, for (the rare?) cases when the compiler generates more efficient code for the explicit bool conversion operator, and users desire such efficiency. - Jeff

On 28.05.2011, at 22:31, Matt Calabrese wrote:
On Sat, May 28, 2011 at 3:23 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
Here's a trial attempt at an implementation of the macro (warning: not tested):
I haven't looked at the implementation in depth, but if I recall correctly, C++0x explicit conversions to bool are not quite the same as a safe-bool conversion (explicit conversions still generally require explicit casts, correct me if I'm wrong).
True. You can only omit the case in "contextual conversion" situations, which are: - Conditions of if, while, do..while and for (maybe switch? not sure). - Arguments to &&, || and !. - First argument to ?:. So these two code examples that a 03 user might write would fail: convertible_to_bool obj; bool b = obj; // must write bool b(obj); void fn(bool); fn(obj); // must cast Sebastian

On Sat, May 28, 2011 at 1:41 PM, Stephan T. Lavavej < stl@exchange.microsoft.com> wrote:
[Jeffrey Lee Hellrung, Jr.]
struct _boost_explicit_operator_bool_struct { int _dummy; int member; }; \
You don't need two data members.
According to Andrey Semashev (to whom I credit the technique to, and should've cited in the above post), you do need two data members, as some compilers interpret a pointer-to-first-member as equal to 0 (i.e., convertible to false). I honestly don't know if such compilers exist or are technically allowed to do that... - Jeff

[Jeffrey Lee Hellrung, Jr.]
struct _boost_explicit_operator_bool_struct { int _dummy; int member; }; \
[STL]
You don't need two data members.
[Jeffrey Lee Hellrung, Jr.]
According to Andrey Semashev (to whom I credit the technique to, and should've cited in the above post), you do need two data members, as some compilers interpret a pointer-to-first-member as equal to 0 (i.e., convertible to false). I honestly don't know if such compilers exist or are technically allowed to do that...
That would be crazy nonconformant. And depressing if true. STL

On Fri, May 27, 2011 at 1:13 PM, Steven Watanabe <watanabesj@gmail.com>wrote:
On Fri, May 27, 2011 at 9:52 AM, Christian Holmquist <c.holmquist@gmail.com>wrote:
On 27 May 2011 11:28, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Krzysztof Czainski wrote:
Vladimir Batov prepared a safebool helper class as part of his Pimpl library.
[snip]
There exists a safebool in already accepted Boost.Log:
I'll chime in for my vote of something more along the lines of Andrey's nullary macro design, except using a pointer-to-member-variable rather
a pointer-to-member-function to address MSVC efficiency concerns (see
On 05/27/2011 11:55 AM, Jeffrey Lee Hellrung, Jr. wrote: than prior
post by S.T. Lavavej). I use something like the following, which I had also picked up from Andrey in a past boost-dev list post.
#define BOOST_EXPLICIT_BOOL() \ private: \ struct _boost_explicit_bool_struct \ { int _dummy; int member; }; \ typedef int (_boost_explicit_bool_struct::*_boost_bool_type); \ public: \ operator _boost_bool_type() const { return !*this ? 0 : &_boost_explicit_bool_struct::member; }
When BOOST_NO_EXPLICIT_CONVERSION_OPERATORS is not defined, then the above macro is defined to just declare an explicit bool conversion, so it amounts to the same framework you would use in C++0x.
I prefer a macro solution over a CRTP solution because 1) it retains POD'ness (in C++03, at least; I believe the definition of POD has been extended in C++0x...?); and 2) the macro appears in the same place one would otherwise declare a bool conversion operator.
I also like the solution to use operator! by default in the implementation of the explicit bool conversion operator; perhaps a second macro could be provided to allow one to specify the specific expression (e.g., "!!*this" or "as_bool()") one should use.
What about a macro that can be used like
BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
Are you thinking something along the lines of #define BOOST_EXPLICIT_BOOL_OPERATOR() \ [...define a safe-bool operator that calls, e.g., _boost_as_bool() to determine true'ness...] \ bool _boost_as_bool() ? - Jeff

On 2011.05.27_13.13.06, Steven Watanabe wrote:
What about a macro that can be used like
BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
In Christ, Steven Watanabe
I like the macro approach, personally, though the one I use works a little differently (see my earlier post in this thread). The MACRO() qualifier { ... } interface you suggested seems more reasonable than mine. -- Bryce Lelbach aka wash boost-spirit.com px.cct.lsu.edu github.com/lll-project

On Fri, May 27, 2011 at 4:13 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
What about a macro that can be used like
BOOST_EXPLICIT_BOOL_OPERATOR() const { return ...; }
In Christ, Steven Watanabe
+1. That's exactly what I was going to suggest (and I typically hate macros). Tony

2011/5/27 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
class boolable : public Base
Why not s/boolable/safe_bool/?
I was trying to find a name than would fit nice into the operators library, together with andable for example. Under the name boolable I understand it may be tested for true/false like if ( x ) ... if ( !x ) ... But I am not against changing the name.
{ void unspecified_bool_t_f() {}
typedef void (boolable::*unspecified_bool_t)();
public:
operator unspecified_bool_t() const { return ! static_cast<Derived const&>( *this ) ? 0 : &boolable::unspecified_bool_t_f;
This doesn't support types that have no other reason to define operator !() or that have a ready-made is_valid() sort of function. IOW, the "valid" or "invalid" function on which to rely should be configurable. (It should be possible to provide either one.)
I understand that you're assuming that if one can write if (x), one might assume that if (!x) should also work, but that should work anyway with the safe-bool operator, right?
Right. So the question is what function should the user provide? I proposed operator!. Other options would be is_valid/is_invalid, to_bool . Or should this function's name be customizable? My choice was to fix this function as operator!, so as not to add anything to the interface. It's like Robert says, "if (!x)" would work anyway even without operator! defined. Regards Kris

Krzysztof Czainski wrote:
2011/5/27 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
class boolable : public Base
Why not s/boolable/safe_bool/?
I was trying to find a name than would fit nice into the operators library, together with andable for example. Under the name boolable I understand it may be tested for true/false like if ( x ) ... if ( !x ) ... But I am not against changing the name.
I see. Unfortunately, "boolable" just sounds horrible to me.
operator unspecified_bool_t() const { return ! static_cast<Derived const&>( *this ) ? 0 : &boolable::unspecified_bool_t_f;
This doesn't support types that have no other reason to define operator !() or that have a ready-made is_valid() sort of function. IOW, the "valid" or "invalid" function on which to rely should be configurable.
Notice that I'm calling for the function to be configurable.
(It should be possible to provide either one.)
Here I suggested that it should be possible to specify a function that indicates the object is valid *or* one that indicates the object is invalid.
I understand that you're assuming that if one can write if (x), one might assume that if (!x) should also work, but that should work anyway with the safe-bool operator, right?
Right. So the question is what function should the user provide? I proposed operator!. Other options would be is_valid/is_invalid, to_bool . Or should this function's name be customizable?
The latter. A policy class would permit installing code to call various derived class functions and to negate the result, if necessary. By default, you can specify a policy class that expects operator !(). That approach would give the default you're currently advocating and give users flexibility to use an existing function rather than create operator !(). That only makes sense if the library user has many classes with some particular function they can use in lieu of operator !() because otherwise, specializing the policy wouldn't be worth the trouble. We have legacy code, for example, that specifies a virtual isValid() member function. A policy class that returns the result of calling derivate::isValid() would be just the ticket for that hierarchy. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 5/27/11 1:01 PM, Matt Calabrese wrote:
On Fri, May 27, 2011 at 3:55 PM, Stewart, Robert<Robert.Stewart@sig.com>wrote:
I see. Unfortunately, "boolable" just sounds horrible to me.
I know it's long, but how about simply "convertible_to_bool".
+1 to that suggestion, since in exchange for a little extra typing it makes what is going on very explicit. Cheers, Greg

[Krzysztof Czainski]
typedef void (boolable::*unspecified_bool_t)();
Note: VC9 and earlier generated terrible code for pointer-to-member-function fake bools, while they generated nearly ideal code for pointer-to-data-member fake bools. While VC10 and later generate nearly ideal code for both, for VC you may as well use pointer-to-data-member all the time. (I don't know about other compilers' codegen.) Stephan T. Lavavej Visual C++ Libraries Developer

Such a class is already in Boost, in two places: /home/wash/development/boost-trunk-wc/boost/range/detail/safe_bool.hpp /home/wash/development/boost-trunk-wc/boost/spirit/core/safe_bool.hpp /home/wash/development/boost-trunk-wc/boost/spirit/home/classic/core/safe_bool.hpp /home/wash/development/boost-trunk-wc/boost/spirit/include/classic_safe_bool.hpp smart_ptr also has a version. Attached is a modified version of this that incorporates portability code from the smart_ptr version into the variant of the spirit safe_bool that Hartmut and I use at work. I like to have a macro for this, so I have an operator that's convertible to the safe_bool class, which is itself convertible to bool (this avoids problem with the need for "typename" in the macro in certain contexts). The safe_bool class is itself convertible to bool. Feel free to incorporate any of this code into whatever comes out of this thread. -- Bryce Lelbach aka wash boost-spirit.com px.cct.lsu.edu github.com/lll-project

Bryce Lelbach wrote:
Attached is a modified version of this that incorporates portability code from the smart_ptr version into the variant of the spirit safe_bool that Hartmut and I use at work.
I like to have a macro for this, so I have an operator that's convertible to the safe_bool class, which is itself convertible to bool (this avoids problem with the need for "typename" in the macro in certain contexts). The safe_bool class is itself convertible to bool.
I like this general approach. First, Peter has great experience in this area, so capitalizing on his work is wise. Second, I like that most of the logic is in a class template rather than in the macro itself. That makes the macro as simple as possible and provides the opportunity to step through the code effecting the conversion should that prove desirable. Third, the use of a macro to tie the class template logic into a UDT doesn't interfere with the inheritance hierarchy and doesn't interfere with POD-ness. Lastly, I like that the expression to indicate validity is passed to the macro, which gives great flexibility and makes it explicit. What I don't like about this approach is that the macro requires a tag argument to ensure uniqueness. This can be eliminated with a bit more code in the macro: #define BOOST_OPERATOR_SAFE_BOOL(_expression) \ struct _safe_bool_tag_ { }; \ typedef ::boost::utility::safe_bool<_safe_bool_tag_> \ safe_bool_type; operator safe_bool_type () const \ { \ return safe_bool_type(_expression); \ } By adding a nested type and using that as the safe_bool parameterizing type, the operator invocation is simplified. Since _safe_bool_tag_ is nested, its fully qualified name is unique to the macro invocation context. As you can see, I'm suggesting that safe_bool<T> be put in Boost.Utility. I'm also suggesting the macro be named "BOOST_OPERATOR_SAFE_BOOL." _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

I tried to put together all, that had been said in this thread, and I prepared boost/utility/safe_bool.hpp (attached). I haven't tested it yet. I took compiler workarounds from <boost/smart_ptr/detail/operator_bool.hpp> To view the file online: http://codepaste.net/c83uuj The file contains the following safe-bool tools: - a CRTP class save_bool_convertilbe<Derived,Base=*,Policy=*>, that implements a conversion operator to a safe-bool in terms of operator! by default, and can be customized by a policy, - a safe_bool_t<tag> - a safe-bool type, implemented in terms of safe_bool_convertible, - 3 macros for defining operator safe-bool inside a class: - BOOST_OPERATOR_SAFE_BOOL_TAGGED(tag,expr) - implemented in terms of safe_bool_t<tag>, - BOOST_OPERATOR_SAFE_BOOL(expr) - which introduces a tag, and is implemented in terms of BOOST_OPERATOR_SAFE_BOOL_TAGGED, - BOOST_EXPLICIT_OPERATOR_BOOL(expr) - which implements an explicit conversion to bool if available, or falls back to BOOST_OPERATOR_SAFE_BOOL otherwise.
From what had been seid in this thread, I understand, that there is interest in all of the above safe-bool tools.
So, does each of these tools deserve its place in boost? Maybe they need to be renamed? What did I miss in the implementation? Regards Kris
participants (13)
-
Bryce Lelbach
-
Christian Holmquist
-
Christopher Jefferson
-
Gottlob Frege
-
Gregory Crosswhite
-
Jeffrey Lee Hellrung, Jr.
-
Krzysztof Czainski
-
Matt Calabrese
-
Sebastian Redl
-
Stephan T. Lavavej
-
Steven Watanabe
-
Stewart, Robert
-
Vicente Botet