Allowing a class to be converted to bool?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Joseph Turian

    Allowing a class to be converted to bool?

    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

    #2
    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;
    }
    .....

    Comment

    • Jonathan Mcdougall

      #3
      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

      Comment

      • Joseph Turian

        #4
        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

        Comment

        • Greg

          #5
          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::*unspecifi ed_bool_type;

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

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

          Now:

          foo f;

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

          Greg

          Comment

          • anujanujdhamija@gmail.com

            #6
            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.

            Comment

            • Jonathan Mcdougall

              #7
              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<in t> 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

              Comment

              • Jonathan Mcdougall

                #8
                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

                Comment

                • puzzlecracker

                  #9
                  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::*unspecifi ed_bool_type;
                  >
                  > public:
                  > foo() : i(0) {}
                  >
                  > operator unspecified_boo l_type() const
                  > {
                  > return i ? &foo::i : NULL;
                  > }
                  > };
                  >
                  > Now:
                  >
                  > foo f;
                  >
                  > if (f) {} // OK
                  > int a = f; // Error
                  >
                  > Greg[/color]
                  typedef unsigned foo::*unspecifi ed_bool_type; --
                  what is ti mean?

                  Comment

                  • peter koch

                    #10
                    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_in t
                    {
                    ...
                    };
                    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 "userfriend ly" name:

                    typedef personalized_in t<0> apple_t;
                    typedef personalized_in t<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]

                    Comment

                    • Greg

                      #11
                      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::*unspecifi ed_bool_type;
                      > >
                      > > public:
                      > > foo() : i(0) {}
                      > >
                      > > operator unspecified_boo l_type() const
                      > > {
                      > > return i ? &foo::i : NULL;
                      > > }
                      > > };
                      > >
                      > > Now:
                      > >
                      > > foo f;
                      > >
                      > > if (f) {} // OK
                      > > int a = f; // Error
                      > >
                      > > Greg[/color]
                      > typedef unsigned foo::*unspecifi ed_bool_type; --
                      > what is ti mean?[/color]

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

                      Greg

                      Comment

                      Working...