|
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