By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,385 Members | 1,763 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,385 IT Pros & Developers. It's quick & easy.

Allowing a class to be converted to bool?

P: n/a
Is it possible to allow a class to be converted to bool?

For example, if I have:
class foo {
private:
unsigned i;
};

and I want to evaluate:
if (foo)
by looking at foo.i, how can I do that?

Thanks

Joseph

Dec 29 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Joseph Turian wrote:
Is it possible to allow a class to be converted to bool?

For example, if I have:
class foo {
private:
unsigned i;
};

and I want to evaluate:
if (foo)
by looking at foo.i, how can I do that?


Use a conversion operator ...

class foo
{
public:
operator bool()
{
return i != 0;
}
.....
Dec 29 '05 #2

P: n/a
Joseph Turian wrote:
Is it possible to allow a class to be converted to bool?

For example, if I have:
class foo {
private:
unsigned i;
};

and I want to evaluate:
if (foo)
by looking at foo.i, how can I do that?


class foo
{
public:
operator bool() const
{
return i != 0;
}

private:
unsigned i;
};

But know that this makes it possible for your class to be converted:

foo f;

if (f) ; // cool
int a = f; // .. also works
Jonathan

Dec 29 '05 #3

P: n/a

Jonathan Mcdougall wrote:
But know that this makes it possible for your class to be converted:

foo f;
if (f) ; // cool
int a = f; // .. also works


Okay wait.

The whole reason I created a class 'foo' which wraps the POD type
'unsigned' is because I want to ensure type-safety by creating several
sub-types of foo.

i.e. I want to have three classes A, B, and C which are essentially of
type 'unsigned'.
However, I want A, B, and C to be considered distinct types and to
have, say, comparisons between A and B types to cause a compiler error.
So, to do so, I want to have A, B, and C inherit from foo.

Question 1: Does having A, B, and C inherit from foo achieve the
desired effect of disallowing comparisons and casts between types A, B,
and C?
Question 2: Does adding the operator bool conversion function open me
to any type-conversion risks?
Thanks!

Joseph

Dec 29 '05 #4

P: n/a
Joseph Turian wrote:
Jonathan Mcdougall wrote:
But know that this makes it possible for your class to be converted:

foo f;
if (f) ; // cool
int a = f; // .. also works


Okay wait.

The whole reason I created a class 'foo' which wraps the POD type
'unsigned' is because I want to ensure type-safety by creating several
sub-types of foo.

i.e. I want to have three classes A, B, and C which are essentially of
type 'unsigned'.
However, I want A, B, and C to be considered distinct types and to
have, say, comparisons between A and B types to cause a compiler error.
So, to do so, I want to have A, B, and C inherit from foo.

Question 1: Does having A, B, and C inherit from foo achieve the
desired effect of disallowing comparisons and casts between types A, B,
and C?
Question 2: Does adding the operator bool conversion function open me
to any type-conversion risks?


Yes. Implicitly converting to a bool would open the door to type
conversions that you probably would not want.

In this case, you can lift a page from boost shared_ptr and return a
dummy member function pointer. Member function pointers are
sufficiently restricted that a program cannot do much with one beyond
testing it for NULL.

class foo
{
private:
unsigned i;

typedef unsigned foo::*unspecified_bool_type;

public:
foo() : i(0) {}

operator unspecified_bool_type() const
{
return i ? &foo::i : NULL;
}
};

Now:

foo f;

if (f) {} // OK
int a = f; // Error

Greg

Dec 29 '05 #5

P: n/a
If you have 3 classes A, B and C which contain unsigned int member.
These cant be compared with each other unless you provide a conversion
operator to a common type (say unsigned int or bool) in each of these
classes or you overload assignment operator in these classes to allow
such comparison.
If you provide a conversion operator say "operator unsigned int()" in
all 3 classes then when you do if(A==B), this conversion function is
called which converts the operands to unsigned int and then compare
these. When you derive A, B and C from another class foo which provides
another conversion operator "operator bool()", then (A==B) will become
ambiguous as there are two possible conversions before comparison. So
this will disallow the comparisons the way you like.
Regarding type-conversion risk, as mentioned by Jonathan, conversion
operator is invoked whenver you use the class object in boolean context
and wont be restricted only to comparisons.

Dec 29 '05 #6

P: n/a
Joseph Turian wrote:
Jonathan Mcdougall wrote:
But know that this makes it possible for your class to be converted:

foo f;
if (f) ; // cool
int a = f; // .. also works
Okay wait.

The whole reason I created a class 'foo' which wraps the POD type
'unsigned' is because I want to ensure type-safety by creating several
sub-types of foo.


Good thing.
i.e. I want to have three classes A, B, and C which are essentially of
type 'unsigned'.
However, I want A, B, and C to be considered distinct types and to
have, say, comparisons between A and B types to cause a compiler error.
So, to do so, I want to have A, B, and C inherit from foo.
"So"? If you want A, B and C yo be considered distinct types, don't
derive them from a base class!
Question 1: Does having A, B, and C inherit from foo achieve the
desired effect of disallowing comparisons and casts between types A, B,
and C?
No, it has no influence. A, B and C cannot be compared or converted
between themselves if you did not write the correct operators. They can
be converted to foo's though.
Question 2: Does adding the operator bool conversion function open me
to any type-conversion risks?


Of course, as do all conversion operators. Consider this:

# include <complex>

class C
{
public:
C(double d);
};

class foo
{
public:
operator bool();
};

int main()
{
foo f;

C c(f); // hmmm
if (f == 'A') ; // oups
std::complex<int> s(f); // what?
}

You could use an operator void* instead:

class foo()
{
public:
operator void*()
{
return i ? &i : 0;
}

private:
int i;
};

If you're careful, that conversion may not be dangerous.

For maximum safety, consider using a named member function. Sometimes,
safety is more important than convenience.
Jonathan

Dec 29 '05 #7

P: n/a
anujanujdham...@gmail.com wrote:
Regarding type-conversion risk, as mentioned by Jonathan, conversion
operator is invoked whenver you use the class object in boolean context
and wont be restricted only to comparisons.


Actually, it would be more accurate to say that this conversion
operator is considered when an integral type is expected.
Jonathan

Dec 29 '05 #8

P: n/a

Greg wrote:
Joseph Turian wrote:
Jonathan Mcdougall wrote:
But know that this makes it possible for your class to be converted:

foo f;
if (f) ; // cool
int a = f; // .. also works


Okay wait.

The whole reason I created a class 'foo' which wraps the POD type
'unsigned' is because I want to ensure type-safety by creating several
sub-types of foo.

i.e. I want to have three classes A, B, and C which are essentially of
type 'unsigned'.
However, I want A, B, and C to be considered distinct types and to
have, say, comparisons between A and B types to cause a compiler error.
So, to do so, I want to have A, B, and C inherit from foo.

Question 1: Does having A, B, and C inherit from foo achieve the
desired effect of disallowing comparisons and casts between types A, B,
and C?
Question 2: Does adding the operator bool conversion function open me
to any type-conversion risks?


Yes. Implicitly converting to a bool would open the door to type
conversions that you probably would not want.

In this case, you can lift a page from boost shared_ptr and return a
dummy member function pointer. Member function pointers are
sufficiently restricted that a program cannot do much with one beyond
testing it for NULL.

class foo
{
private:
unsigned i;

typedef unsigned foo::*unspecified_bool_type;

public:
foo() : i(0) {}

operator unspecified_bool_type() const
{
return i ? &foo::i : NULL;
}
};

Now:

foo f;

if (f) {} // OK
int a = f; // Error

Greg

typedef unsigned foo::*unspecified_bool_type; --
what is ti mean?

Dec 29 '05 #9

P: n/a

Joseph Turian skrev:
Jonathan Mcdougall wrote:
But know that this makes it possible for your class to be converted:

foo f;
if (f) ; // cool
int a = f; // .. also works
Okay wait.

The whole reason I created a class 'foo' which wraps the POD type
'unsigned' is because I want to ensure type-safety by creating several
sub-types of foo.

i.e. I want to have three classes A, B, and C which are essentially of
type 'unsigned'.
However, I want A, B, and C to be considered distinct types and to
have, say, comparisons between A and B types to cause a compiler error.
So, to do so, I want to have A, B, and C inherit from foo.


There is no need to inherit - as Jonathan told you.

An elegant way to allow many such similar classes and have them be
distinct would be to use a template:

template<int id> class personalized_int
{
...
};
The only purpose of the template would be to faciliate the easy
creation of new types - so inside the class template, everything will
look as if the class was nontemplated.

When you're done you can use a typedef to get to a "userfriendly" name:

typedef personalized_int<0> apple_t;
typedef personalized_int<1> orange_t;
orange_t oranges = 10;
apple_t apples = 30;

if (apples < oranges) // causes compile-error
/Peter
Question 1: Does having A, B, and C inherit from foo achieve the
desired effect of disallowing comparisons and casts between types A, B,
and C?
Question 2: Does adding the operator bool conversion function open me
to any type-conversion risks?
Thanks!

Joseph


Dec 29 '05 #10

P: n/a
puzzlecracker wrote:
Greg wrote:
Joseph Turian wrote:
Jonathan Mcdougall wrote:

> But know that this makes it possible for your class to be converted:
>
> foo f;
> if (f) ; // cool
> int a = f; // .. also works

Okay wait.

The whole reason I created a class 'foo' which wraps the POD type
'unsigned' is because I want to ensure type-safety by creating several
sub-types of foo.

i.e. I want to have three classes A, B, and C which are essentially of
type 'unsigned'.
However, I want A, B, and C to be considered distinct types and to
have, say, comparisons between A and B types to cause a compiler error.
So, to do so, I want to have A, B, and C inherit from foo.

Question 1: Does having A, B, and C inherit from foo achieve the
desired effect of disallowing comparisons and casts between types A, B,
and C?
Question 2: Does adding the operator bool conversion function open me
to any type-conversion risks?


Yes. Implicitly converting to a bool would open the door to type
conversions that you probably would not want.

In this case, you can lift a page from boost shared_ptr and return a
dummy member function pointer. Member function pointers are
sufficiently restricted that a program cannot do much with one beyond
testing it for NULL.

class foo
{
private:
unsigned i;

typedef unsigned foo::*unspecified_bool_type;

public:
foo() : i(0) {}

operator unspecified_bool_type() const
{
return i ? &foo::i : NULL;
}
};

Now:

foo f;

if (f) {} // OK
int a = f; // Error

Greg

typedef unsigned foo::*unspecified_bool_type; --
what is ti mean?


It's a typedef declaration that makes the name "unspecified_bool_type"
an alias for a data member pointer to an unsigned int data member of
foo. The subsequent unspecified_bool_type conversion operator returns
such a data member pointer when i is not 0 or NULL otherwise.

Greg

Dec 29 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.