views:

129

answers:

4

Is it possible to have a class object return a true/false value, so I can do something like this:

MyClass a;
...
if (a)
    do_something();

I can accomplish (almost) what I want by overloading the ! operator:

class MyClass {
    ...
    bool operator!() const { return !some_condition; };
    ...
}

main()
    MyClass a;
    ...
    if (!a)
        do_something_different();

but I haven't found a way to overload what would be the "empty" operator. Of course, using the == operator to check for true/false is also possible, and is in fact what I have been doing so far.

+8  A: 

Overload the void * cast operator:

operator void * () const { return some_condition; };

this is how streams work, allowing you to say:

if ( cin ) {
   // stream is OK
}

The use of void * rather than bool prevents the cast being used by mistake in some contexts, such as arithmetic, where it would not be desirable. Unless, you want to use it in those contexts, of course.

anon
The `bool` operator is more specific than the `void *` one. Could you please show an example of mistake involving cast to bool?
Dacav
Thanks. This works just fine, except I had to cast some_condition into (void*). However, everyone else here suggests overloading bool(), which also works just fine and makes the code looks easier to understand :) Could you please give an example of where things could go wrong with that solution, so I can better understand the benefits of your suggestion?
Terje Mikal
@Dacav I don't know what you men by more specific - a void * cannot be part of an arithmetic expression so the class cannot be used in the form `a + 1`, which as I suggested may or may not be what the OP wants.
anon
@Terje See comment above. and I've edited my answer slightly.
anon
@Neil Butterworth: thanks, now I see the problem. I tried to cout something like `static_cast<int>(3 + m)` where m is an instance of a class overloading bool, and the compiler actually accepted it!
Dacav
Yes, thanks Neil. That is a very valid point you've made as this solution would catch such mistakes at compile-time. So if no one else comes up with an even better solution or valid counter-arguments within the next day, I'll mark this as the accepted answer.
Terje Mikal
@Terje Mikal: The safe bool idiom is even better, see (and accept) sbk's answer.
Philipp
Adding an implicit cast to `void*` enables `delete a;`.
Philipp
@Phillip On g++ you get `warning: deleting 'void*' is undefined`
anon
A: 

Try overloading the (bool) operator:

operator bool() { /* ... */ }
dark_charlie
Bad idea, and discouraged. See Neil’s answers for details.
Konrad Rudolph
-1 this has unintended side effects, see the Safe Bool Idiom for an alternative solution.
Sam Miller
+6  A: 

The obvious solution – providing an implicit conversion to bool via operator bool – is a bad idea.

That’s why the standard library uses operator void* as shown in Neil’s answer.

However, it’s worth pointing out that even this solution has flaws and is therefore no longer considered safe. Unfortunately, coming up with a better solution isn’t trivial …

There’s an article over at Artima that describes the safe bool idiom. For a real library, this is definitely the way to go, since it offers the most robust interface that is hardest to use wrong.

Konrad Rudolph
It is also the most complicated approach. It may be worth asking "do I need to be able to use the class directly where a bool is expected?" May be simpler and saner to just provide a `is_ok` member function, or perhaps overload `operator()` to return a bool and then test `if (a())` instead.
jalf
Thanks for the link, Konrad (and sbk). That was very interesting reading, and certainly something to keep for future reference.
Terje Mikal
@jalf: true, this is why I added that “for real libraries …”. The point is, for a library, the benefit to the user *always* outweighs the effort of the implementor. A hard-to-use and easy interface wins, hands down.
Konrad Rudolph
+5  A: 

Weird, no one has mentioned the safe bool idiom so far. All the other solutions described so far have drawbacks (which you might or might not care about), all those approaches are described in the article. In a nutshell, the safe bool idiom goes something like this:

  class Testable {
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    operator bool_type() const {
      return /* condition here */ ? 
        &Testable::this_type_does_not_support_comparisons  // true value
        : 0; // false value
    }
  };
sbk
At least one of the "problems" described in the article, deleting the result of a void * cast, is a bit dubious. All compilers I use give a at least a warning on this, as it is UB.
anon
Yes, I'm deleting my suggestion of casting to bool as it's misleadingly flawed.If you really want it to be treated like a bool in all contexts, then casting to bool is perfect. Casting to void* has its value, but its flaws also. This is the general solution to go for, with casting to bool being the one to go for if it **really** should be treated as a bool in all contexts.
Jon Hanna
AFAIK, in C++0x you will be able to mark conversion operators **explicit**, removing the need for a safe bool idiom?
UncleBens