overloading for specific implicit casts

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Simon Ford

    overloading for specific implicit casts

    Hi All,

    I'm having trouble understanding exactly how I can do some specific implicit
    casting. There are two problems here; does anyone know what I should be
    doing?

    //----------
    // (1) Resolving as bool for comparison, but not as int.
    //
    // we have a class

    class Foo{};
    Foo x;

    // I want to allow for a test of class Foo (i.e. returning bool)

    if(x) {}

    // which is probably done using : operator bool() const
    // However, I don't want the compiler to allow this implicit cast
    // to go through bool to int:

    int y = 5;
    int z = x + y; // should be an error

    // i.e. z should not become 6, it should throw a compile error
    // How do I allow the implicit boolean conversion without allowing
    // the further integer conversion?
    //----------
    // (2) Casting from another type
    //
    // we have some operators overloaded:

    bool operator== (Foo& lhs, Foo& rhs);

    // Now, I would like to allow an implicit cast from another chosen type
    // (string) to allow a comparison:

    if(x == "bar") {} // "bar" is implicitly cast to a Foo of flavour bar

    // i.e. avoiding having to define the two other variants for every operator

    bool operator== (string lhs, Foo& rhs); // don't want to define this!
    bool operator== (Foo& lhs, string rhs); // don't want to define this!

    // How would I go about doing this?
    //----------

    Thanks for your time,
    Simon ;o)


  • tom_usenet

    #2
    Re: overloading for specific implicit casts

    On Mon, 22 Sep 2003 11:19:53 +0100, "Simon Ford"
    <simon_news@moo kstar.co.uk> wrote:
    [color=blue]
    >Hi All,
    >
    >I'm having trouble understanding exactly how I can do some specific implicit
    >casting. There are two problems here; does anyone know what I should be
    >doing?
    >
    >//----------
    >// (1) Resolving as bool for comparison, but not as int.
    >//
    >// we have a class
    >
    >class Foo{};
    >Foo x;
    >
    >// I want to allow for a test of class Foo (i.e. returning bool)
    >
    >if(x) {}
    >
    >// which is probably done using : operator bool() const
    >// However, I don't want the compiler to allow this implicit cast
    >// to go through bool to int:
    >
    >int y = 5;
    >int z = x + y; // should be an error
    >
    >// i.e. z should not become 6, it should throw a compile error
    >// How do I allow the implicit boolean conversion without allowing
    >// the further integer conversion?[/color]

    The usual technique is to implement operator void* rather than
    operator bool. void* can't take part in pointer arithmetic, can't be
    assigned to any other built in types, but does convert conveniently to
    a bool. e.g. something like this:

    operator void const*() const
    {
    if(I'm true)
    return this;//must return a valid non-null address; "this" will do
    else
    return 0;
    }

    The iostreams heirarchy uses this trick.
    [color=blue]
    >//----------
    >// (2) Casting from another type
    >//
    >// we have some operators overloaded:
    >
    >bool operator== (Foo& lhs, Foo& rhs);
    >
    >// Now, I would like to allow an implicit cast from another chosen type
    >// (string) to allow a comparison:
    >
    >if(x == "bar") {} // "bar" is implicitly cast to a Foo of flavour bar
    >
    >// i.e. avoiding having to define the two other variants for every operator
    >
    >bool operator== (string lhs, Foo& rhs); // don't want to define this!
    >bool operator== (Foo& lhs, string rhs); // don't want to define this!
    >
    >// How would I go about doing this?[/color]

    Provide a Foo constructor that takes a string. e.g.

    Foo(std::string const& s);
    or possibly
    Foo(std::string s);

    Tom

    Comment

    • David B. Held

      #3
      Re: overloading for specific implicit casts

      "tom_usenet " <tom_usenet@hot mail.com> wrote in message
      news:pqntmvcftf egivsc008ebl8ke 15tjp3fgt@4ax.c om...[color=blue]
      > [...]
      > The usual technique is to implement operator void* rather
      > than operator bool. void* can't take part in pointer arithmetic,
      > can't be assigned to any other built in types, but does
      > convert conveniently to a bool. e.g. something like this:
      > [...][/color]

      Even better than that is the trick used in Loki::SmartPtr or
      boost::shared_p tr. I'll show the Boost version here, because
      it's shorter:

      typedef T * (this_type::*un specified_bool_ type)() const;

      operator unspecified_boo l_type() const // never throws
      {
      return px == 0? 0: &this_type::get ;
      }

      The difference between this and void* is that the delete
      expression is no longer legal, so the compiler is required
      to diagnose it (as opposed to silently invoking undefined
      behaviour).

      Note that there is currently discussion that a pointer-to-
      member might be even more desirable than a pointer-to-
      member-function.

      Loki makes a private class and makes the delete operator
      private and returns a pointer to that class. That achieves
      the same goal.

      Dave


      Comment

      • Simon Ford

        #4
        Re: overloading for specific implicit casts

        Thanks for the response - half good news, half bad news...
        [color=blue][color=green]
        > >// I want to allow for a test of class Foo (i.e. returning bool)
        > >
        > >if(x) {}[/color]
        > The usual technique is to implement operator void* rather than
        > operator bool. void* can't take part in pointer arithmetic, can't be
        > assigned to any other built in types, but does convert conveniently to
        > a bool. e.g. something like this:
        >
        > operator void const*() const
        > {
        > if(I'm true)
        > return this;//must return a valid non-null address; "this" will do
        > else
        > return 0;
        > }[/color]

        This seemed to work, thanks.
        [color=blue][color=green]
        > >//----------
        > >// (2) Casting from another type
        > >//
        > >// we have some operators overloaded:
        > >
        > >bool operator== (Foo& lhs, Foo& rhs);
        > >
        > >// Now, I would like to allow an implicit cast from another chosen type
        > >// (string) to allow a comparison:
        > >
        > >if(x == "bar") {} // "bar" is implicitly cast to a Foo of flavour bar
        > >
        > >// i.e. avoiding having to define the two other variants for every[/color][/color]
        operator[color=blue][color=green]
        > >
        > >bool operator== (string lhs, Foo& rhs); // don't want to define this!
        > >bool operator== (Foo& lhs, string rhs); // don't want to define this!
        > >
        > >// How would I go about doing this?[/color]
        >
        > Provide a Foo constructor that takes a string. e.g.
        >
        > Foo(std::string const& s);
        > or possibly
        > Foo(std::string s);[/color]

        I thought this should be enough too, but it complains there is no acceptable
        conversion. Any other ideas?

        Thanks again,
        Simon.



        Comment

        • tom_usenet

          #5
          Re: overloading for specific implicit casts

          On Tue, 23 Sep 2003 15:57:24 +0100, "Simon Ford"
          <simon_news@moo kstar.co.uk> wrote:
          [color=blue][color=green]
          >> Provide a Foo constructor that takes a string. e.g.
          >>
          >> Foo(std::string const& s);
          >> or possibly
          >> Foo(std::string s);[/color]
          >
          >I thought this should be enough too, but it complains there is no acceptable
          >conversion. Any other ideas?[/color]

          Your operator== signature is a non-member function like this, right?

          bool operator==(Foo const& lhs, Foo const& rhs);

          If you miss out the const, you can't pass temporaries to the method...

          Tom

          Comment

          Working...