Connecting Tech Pros Worldwide Forums | Help | Site Map

Allowing a class to be converted to bool?

Joseph Turian
Guest
 
Posts: n/a
#1: Dec 29 '05
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


Gianni Mariani
Guest
 
Posts: n/a
#2: Dec 29 '05

re: Allowing a class to be converted to bool?


Joseph Turian wrote:[color=blue]
> 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?[/color]

Use a conversion operator ...

class foo
{
public:
operator bool()
{
return i != 0;
}
.....
Jonathan Mcdougall
Guest
 
Posts: n/a
#3: Dec 29 '05

re: Allowing a class to be converted to bool?


Joseph Turian wrote:[color=blue]
> 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?[/color]

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

Joseph Turian
Guest
 
Posts: n/a
#4: Dec 29 '05

re: Allowing a class to be converted to bool?



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

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

Greg
Guest
 
Posts: n/a
#5: Dec 29 '05

re: Allowing a class to be converted to bool?


Joseph Turian wrote:[color=blue]
> Jonathan Mcdougall wrote:
>[color=green]
> > But know that this makes it possible for your class to be converted:
> >
> > foo f;
> > if (f) ; // cool
> > int a = f; // .. also works[/color]
>
> 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?[/color]

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

anujanujdhamija@gmail.com
Guest
 
Posts: n/a
#6: Dec 29 '05

re: Allowing a class to be converted to bool?


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.

Jonathan Mcdougall
Guest
 
Posts: n/a
#7: Dec 29 '05

re: Allowing a class to be converted to bool?


Joseph Turian wrote:[color=blue]
> Jonathan Mcdougall wrote:
>[color=green]
> > But know that this makes it possible for your class to be converted:
> >
> > foo f;
> > if (f) ; // cool
> > int a = f; // .. also works[/color]
>
> 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.[/color]

Good thing.
[color=blue]
> 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.[/color]

"So"? If you want A, B and C yo be considered distinct types, don't
derive them from a base class!
[color=blue]
> 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?[/color]

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.
[color=blue]
> Question 2: Does adding the operator bool conversion function open me
> to any type-conversion risks?[/color]

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

Jonathan Mcdougall
Guest
 
Posts: n/a
#8: Dec 29 '05

re: Allowing a class to be converted to bool?


anujanujdham...@gmail.com wrote:[color=blue]
> 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.[/color]

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


Jonathan

puzzlecracker
Guest
 
Posts: n/a
#9: Dec 29 '05

re: Allowing a class to be converted to bool?



Greg wrote:[color=blue]
> Joseph Turian wrote:[color=green]
> > Jonathan Mcdougall wrote:
> >[color=darkred]
> > > But know that this makes it possible for your class to be converted:
> > >
> > > foo f;
> > > if (f) ; // cool
> > > int a = f; // .. also works[/color]
> >
> > 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?[/color]
>
> 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[/color]
typedef unsigned foo::*unspecified_bool_type; --
what is ti mean?

peter koch
Guest
 
Posts: n/a
#10: Dec 29 '05

re: Allowing a class to be converted to bool?



Joseph Turian skrev:
[color=blue]
> Jonathan Mcdougall wrote:
>[color=green]
> > But know that this makes it possible for your class to be converted:
> >
> > foo f;
> > if (f) ; // cool
> > int a = f; // .. also works[/color]
>
> 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.[/color]

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[color=blue]
>
> 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[/color]

Greg
Guest
 
Posts: n/a
#11: Dec 29 '05

re: Allowing a class to be converted to bool?


puzzlecracker wrote:[color=blue]
> Greg wrote:[color=green]
> > Joseph Turian wrote:[color=darkred]
> > > 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?[/color]
> >
> > 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[/color]
> typedef unsigned foo::*unspecified_bool_type; --
> what is ti mean?[/color]

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

Closed Thread