Boost logo

Boost :

From: Daniel Wallin (dalwan01_at_[hidden])
Date: 2003-11-28 08:59:51


Daniel James wrote:
> 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:
>
> [snip]

Here's another one:

template <class T>
struct bool_testable
{
protected:
     bool_testable()
     {
         BOOST_STATIC_ASSERT(!(
             boost::is_convertible<T, int>::value)
         );
     }

     struct bool_
     {
         bool_(bool x_) : x(x_) {}
         bool x;
     };

private:
     typedef bool bool_::*safe_bool;
public:
     operator safe_bool() const
     {
         return static_cast<T const&>(*this).operator bool_().x
             ? &bool_::x
             : 0;
     }
};

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

... And another one:

template <class T>
struct bool_testable
{
protected:
     bool_testable()
     {
         BOOST_STATIC_ASSERT(!(
             boost::is_convertible<T, int>::value)
         );
     }

private:
     struct impl { bool x; };
     typedef bool impl::*safe_bool;
     struct need_to_implement_operator_not {};

public:
     operator safe_bool() const
     {
         return !static_cast<T const&>(*this)
             ? 0
             : &impl::x;
     }

     need_to_implement_operator_not operator!() const;
};

struct X : bool_testable<X>
{
     bool operator!() const { return false; }
};

-- 
Daniel Wallin

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