Boost logo

Boost :

From: Daniel James (daniel.james_at_[hidden])
Date: 2003-11-28 08:08:02


On Thu, 27 Nov 2003 16:33:10 -0500, David Abrahams wrote:

> What am I missing?
>
> template <class T>
> struct bool_testable
> {
> private:
> struct impl { int x; };
> typedef int impl::*safe_bool;
> public:
> operator safe_bool() const
> {
> return !*static_cast<T const*>(this) ? 0 : &impl::x;
> }
> };
>
> struct X : bool_testable<X>
> {
> bool operator!() const { return true; }
> };

If a user forgets to make their operator! const, then it can't be called,
so the compiler uses a cast to safe_bool in order to apply ! to that (or
at least it does in gcc). This causes infinite recursion. As this is a
fairly easy mistake to make, I'd see it as a problem.

It could be rewritten to explicitly call operator!(), but that would mean
that operator!() would have to be a member function. But that might be too
limiting?

Personally, I like Joel de Guzman's version, but I also like using boost
operators, so for me a mix of the two would be good:

template <class T>
struct bool_testable
{
private:
    struct impl { int x; };
protected:
    typedef int impl::*safe_bool;
    static safe_bool make_safe_bool(bool cond)
    {
        return cond ? &impl::x : 0;
    }
public:
    bool operator!() const
    {
        return !static_cast<T const&>(&this).operator safe_bool();
    }
};

struct X : bool_testable<X>
{
    operator safe_bool() const { return make_safe_bool(false); }
};

Daniel


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk