views:

122

answers:

4

With all of the fundamental types of C++, one can simply query:

if(varname)

and the type is converted to a boolean for evaluation. Is there any way to replicate this functionality in a user-defined class? One of my classes is identified by an integer, although it has a number of other members, and I'd like to be able to check if the integer is set to NULL in such a manner.

Thanks.

+4  A: 

Simply implement operator bool() for your class.

e.g.

class Foo
{
public:
    Foo(int x) : m_x(x) { }
    operator bool() const { return (0 != m_x); }
private:
    int m_x;
}

Foo a(1);
if (a) { // evaluates true
    // ...
}

Foo b(-1);
if (b) { // evaluates true
    // ...
}

Foo c(0);
if (c) { // evaluates false
    // ...
}
Gareth Stockwell
-1, this breaks easily in unobvious ways. Look up the "Safe Bool Idiom."
greyfade
C++0x has `explicit operator bool()` to avoid implicit breakage of the kind?
UncleBens
@grayfade: agreed - this solution is not ideal and the Safe Bool idiom is a more robust approach.
Gareth Stockwell
+7  A: 

You can define a user-defined conversion operator. This must be a member function, e.g.:

class MyClass {
  operator int() const
  { return your_number; }
  // other fields
};

You can also implement operator bool. However, I would STRONGLY suggest against doing it because your class will become usable in arithmetic expressions which can quickly lead to a mess. IOStreams define, for example, conversion to void*. You can test void* in the same way you can test a bool, but there are no language-defined implicit conversions from void*. Another alternative is to define operator! with the desired semantics.

In short: defining conversion operator sto integer types (including booleans) is a REALLY bad idea.

zvrba
You state that conversion to integer types is a bad idea .. but then this is exactly what your code snippet does. Agreed that `operator bool()` has unintended consequences and there are better solutions. But conversion to void* is not perfect either: `Foo x; delete x;` will now compile. `bool operator!()` is better, but you still need to do `if (!!x)` to test for the positive case. As suggested in another comment, the Safe Bool idiom is the best solution.
Gareth Stockwell
1) The OP clearly did not know the syntax for defining conversion operators, otherwise he would have been able to code the most trivial solution. So he learned something new. 2) I warned him about this being a bad idea. 3) Safe bool is better, but seems like an overengineering. If conversion to void* is good for the standard library, it's good for me too.
zvrba
A: 

C++ checks if the statements result is whether equal to zero nor not. So i think you can define equality operator for your class and define how your class will be different from zero in which conditions.

LostMohican
Not really... the value is converted to a boolean. It is just that in general the conversion is done from `0` to `false` and from anything else to `true`. The important difference is that if you define `bool operator==( type const` and `bool operator==( int, type const ` you can compare your object to `0` but you cannot use the object as a condition.
David Rodríguez - dribeas
+1  A: 

As others have stated, using operator int () or operator bool () is bad idea because of the conversions it allows. Using a pointer is better idea. The best know solution to this problem so far is to return a member (function) pointer:

class MyClass {
  void some_function () {}

  typedef void (MyClass:: * safe_bool_type) ();
  operator safe_bool_type () const
  { return cond ? &MyClass::some_function : 0; }
};
wilx