g++ const 'this' problems

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Calcote

    g++ const 'this' problems

    I'm not sure is there's a g++ specific newsgroup...

    g++ is telling me there's a const-related problem with my source code
    and I just don't see it. Now, I don't know that it means much, but VC7
    doesn't see the problem either:

    ----snip-snip-snip----

    #include <string>
    #include <set>

    using namespace std;

    class X {
    class Y {
    set<string> _bound;
    public:
    void Bind(const string & x);
    };

    set<Y> _requests;
    public:
    void ApplyChanges(co nst set<string> & changes);
    };

    void X::Y::Bind(cons t std::string & data)
    {
    _bound.insert(d ata);
    }

    void X::ApplyChanges (const set<string> & changes)
    {
    set<Y>::iterato r rip;
    set<string>::co nst_iterator ip;
    for (ip = changes.begin() ; ip != changes.end(); ++ip)
    for (rip = _requests.begin (); rip != _requests.end() ; ++rip)
    rip->Bind(*ip);
    }

    int main(void)
    {
    X x;
    return 0;
    }

    ----snip-snip-snip----

    This source causes the following error messages:

    test.cpp: In member function `void X::ApplyChanges (const
    std::set<std::s tring,
    std::less<std:: string>, std::allocator< std::string> >&)':
    test.cpp:30: passing `const X::Y' as `this' argument of `void
    X::Y::Bind(cons t
    std::string&)' discards qualifiers

    Now, I can't for the life of me see how I'm violating const rules
    here. I'm not passing a const 'this' pointer. I'm passing a const
    parameter, true, but it's not the this pointer.

    Any ideas?
    John
  • Gianni Mariani

    #2
    Re: g++ const 'this' problems

    John Calcote wrote:[color=blue]
    > I'm not sure is there's a g++ specific newsgroup...
    >
    > g++ is telling me there's a const-related problem with my source code
    > and I just don't see it. Now, I don't know that it means much, but VC7
    > doesn't see the problem either:
    >
    > ----snip-snip-snip----
    >
    > #include <string>
    > #include <set>
    >
    > using namespace std;
    >
    > class X {
    > class Y {
    > set<string> _bound;
    > public:
    > void Bind(const string & x);
    > };
    >
    > set<Y> _requests;
    > public:
    > void ApplyChanges(co nst set<string> & changes);
    > };
    >
    > void X::Y::Bind(cons t std::string & data)
    > {
    > _bound.insert(d ata);
    > }
    >
    > void X::ApplyChanges (const set<string> & changes)
    > {
    > set<Y>::iterato r rip;
    > set<string>::co nst_iterator ip;
    > for (ip = changes.begin() ; ip != changes.end(); ++ip)
    > for (rip = _requests.begin (); rip != _requests.end() ; ++rip)
    > rip->Bind(*ip);[/color]

    I changed that code to this:

    Y * pr_rip = &(* rip);
    pr_rip->Bind(*ip);

    gcc_constthis.c pp:30: error: invalid conversion from `const X::Y*' to
    `X::Y*'

    It seems at though it is a const_iterator.

    Looks like a gcc bug.

    It compiles fine on VC++7.1.
    [color=blue]
    > }
    >
    > int main(void)
    > {
    > X x;
    > return 0;
    > }
    >
    > ----snip-snip-snip----
    >
    > This source causes the following error messages:
    >
    > test.cpp: In member function `void X::ApplyChanges (const
    > std::set<std::s tring,
    > std::less<std:: string>, std::allocator< std::string> >&)':
    > test.cpp:30: passing `const X::Y' as `this' argument of `void
    > X::Y::Bind(cons t
    > std::string&)' discards qualifiers
    >
    > Now, I can't for the life of me see how I'm violating const rules
    > here. I'm not passing a const 'this' pointer. I'm passing a const
    > parameter, true, but it's not the this pointer.
    >
    > Any ideas?
    > John[/color]

    Comment

    • Artie Gold

      #3
      Re: g++ const 'this' problems

      John Calcote wrote:[color=blue]
      > I'm not sure is there's a g++ specific newsgroup...
      >[/color]
      There is: news:gnu.g++.he lp

      [snip]
      [Everything else dealt with elsethread.]

      Cheers,
      --ag

      --
      Artie Gold -- Austin, Texas
      Oh, for the good old days of regular old SPAM.

      Comment

      • tom_usenet

        #4
        Re: g++ const 'this' problems

        On 19 Dec 2003 14:27:10 -0800, jcalcote@novell .com (John Calcote)
        wrote:
        [color=blue]
        >I'm not sure is there's a g++ specific newsgroup...
        >
        >g++ is telling me there's a const-related problem with my source code
        >and I just don't see it. Now, I don't know that it means much, but VC7
        >doesn't see the problem either:[/color]

        It seems GCC is ahead of the game, already having implemented this
        defect report:


        Tom

        C++ FAQ: http://www.parashift.com/c++-faq-lite/
        C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

        Comment

        • Rob Williscroft

          #5
          Re: g++ const 'this' problems

          John Calcote wrote in news:abb28ce2.0 312191427.5c513 e71@posting.goo gle.com:
          [color=blue]
          > I'm not sure is there's a g++ specific newsgroup...
          >
          >g++ is telling me there's a const-related problem with my source code
          > and I just don't see it. Now, I don't know that it means much, but VC7
          > doesn't see the problem either:
          >[/color]

          VC7 is wrong, If there is any doubt about this it compiles this
          nonsence:

          #include <iostream>
          #include <ostream>
          #include <set>

          using namespace std;

          int main()
          {
          set< int > si;
          for ( int i = 0; i < 10; ++i ) si.insert( i );

          *si.find( 2 ) = 4;

          set< int >::iterator ptr, lim;

          for ( ptr = si.begin(), lim = si.end(); ptr != lim; ++ptr )
          {
          cout << *ptr << endl;
          }
          }

          This compiles with VC 7.1 ( Dinkumware Standard library 313 ).

          Anyway, your original code with some addition's/fixes:

          #include <string>
          #include <set>

          using namespace std;

          class X {
          class Y {
          mutable set<string> _bound;
          int key;
          static int static_key;

          public:

          void Bind(const string & x) const;
          Y() : key( ++static_key ) {}
          bool operator < ( Y const &rhs ) const
          {
          return key < rhs.key;
          }
          };

          set<Y> _requests;
          public:
          void ApplyChanges(co nst set<string> & changes);
          void add_request()
          {
          _requests.inser t( Y() );
          }
          };

          int X::Y::static_ke y = 0;

          void X::Y::Bind(cons t std::string & data) const
          {
          _bound.insert(d ata);
          }

          void X::ApplyChanges (const set<string> & changes)
          {
          set<Y>::iterato r rip;
          set<string>::co nst_iterator ip;
          for (ip = changes.begin() ; ip != changes.end(); ++ip)
          for (rip = _requests.begin (); rip != _requests.end() ; ++rip)
          rip->Bind(*ip);
          }


          int main(void)
          {
          X x;

          x.add_request() ;

          set< string > ss;

          ss.insert( " a " );

          x.ApplyChanges( ss );

          return 0;
          }
          [color=blue]
          >
          > This source causes the following error messages:
          >
          > test.cpp: In member function `void X::ApplyChanges (const
          > std::set<std::s tring,
          > std::less<std:: string>, std::allocator< std::string> >&)':
          > test.cpp:30: passing `const X::Y' as `this' argument of `void
          > X::Y::Bind(cons t
          > std::string&)' discards qualifiers
          >
          > Now, I can't for the life of me see how I'm violating const rules
          > here. I'm not passing a const 'this' pointer. I'm passing a const
          > parameter, true, but it's not the this pointer.
          >[/color]

          std::set< T > should store T const's not T's, your looking at the wrong
          "this", the error message is refering to the Y const * you were
          using as a "this" paramiter to Y::Bind().

          Note all the cruft I added to get this to compile, you might want to
          think about changing, set< Y > _requests; to std::map< SomeKey, Y >.

          HTH.

          Rob.
          --

          Comment

          • tom_usenet

            #6
            Re: g++ const 'this' problems

            On 19 Dec 2003 23:55:57 GMT, Rob Williscroft
            <rtw@freenet.RE MOVE.co.uk> wrote:
            [color=blue]
            >VC7 is wrong, If there is any doubt about this it compiles this
            >nonsence:
            >
            >#include <iostream>
            >#include <ostream>
            >#include <set>
            >
            >using namespace std;
            >
            >int main()
            >{
            > set< int > si;
            > for ( int i = 0; i < 10; ++i ) si.insert( i );
            >
            > *si.find( 2 ) = 4;
            >
            > set< int >::iterator ptr, lim;
            >
            > for ( ptr = si.begin(), lim = si.end(); ptr != lim; ++ptr )
            > {
            > cout << *ptr << endl;
            > }
            >}
            >
            >This compiles with VC 7.1 ( Dinkumware Standard library 313 ).[/color]

            And so it should - the code is well-formed according to the current
            standard (set::value_typ e is non-const according to std::set's
            synopsis, set::iterator:: value_type is also non-const according to
            container requirements). Obviously the code has undefined behaviour
            (since a key is modified in such a way as to affect its ordering). See



            Tom

            C++ FAQ: http://www.parashift.com/c++-faq-lite/
            C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

            Comment

            • Jerry Coffin

              #7
              Re: g++ const 'this' problems

              In article <Xns9456F34B329 62ukcoREMOVEfre enetrtw@195.129 .110.201>,
              rtw@freenet.REM OVE.co.uk says...

              [ ... ]
              [color=blue]
              > VC7 is wrong, If there is any doubt about this it compiles this
              > nonsence:[/color]

              This is one of those places that's open to a lot of argument, at best.
              Despite being more or less nonsensical, the standard requires a
              conforming implementation to accept the code.

              In any case, the library working group of the C++ committee has drafted
              a proposal for fixing this part of the standard, and it'll almost
              certainly end up in a TC or somesuch eventually. The proposal basically
              says that for a set (among other things) the key will be immutable, and
              both iterator and const_iterator will be const, so you won't be able to
              modify the key as you've done.

              Nonetheless, that's not part of the standard yet, so to follow the
              standard as it currently stands, the compiler must accept the code.
              There's a comment in the standard that more or less implies that if you
              modify a key, the modification should not alter the ordering. Based on
              that, I think a case could be made for saying that your code has
              undefined behavior, meaning nothing the compiler does with it is really
              wrong.

              --
              Later,
              Jerry.

              The universe is a figment of its own imagination.

              Comment

              • Gianni Mariani

                #8
                Re: g++ const 'this' problems

                Jerry Coffin wrote:[color=blue]
                > In article <Xns9456F34B329 62ukcoREMOVEfre enetrtw@195.129 .110.201>,
                > rtw@freenet.REM OVE.co.uk says...
                >
                > [ ... ]
                >
                >[color=green]
                >>VC7 is wrong, If there is any doubt about this it compiles this
                >>nonsence:[/color]
                >
                >
                > This is one of those places that's open to a lot of argument, at best.
                > Despite being more or less nonsensical, the standard requires a
                > conforming implementation to accept the code.
                >
                > In any case, the library working group of the C++ committee has drafted
                > a proposal for fixing this part of the standard, and it'll almost
                > certainly end up in a TC or somesuch eventually. The proposal basically
                > says that for a set (among other things) the key will be immutable, and
                > both iterator and const_iterator will be const, so you won't be able to
                > modify the key as you've done.
                >
                > Nonetheless, that's not part of the standard yet, so to follow the
                > standard as it currently stands, the compiler must accept the code.
                > There's a comment in the standard that more or less implies that if you
                > modify a key, the modification should not alter the ordering. Based on
                > that, I think a case could be made for saying that your code has
                > undefined behavior, meaning nothing the compiler does with it is really
                > wrong.
                >[/color]

                Strictly speaking, you're 100% correct, however, in any case, gcc
                behaviour is probably is *wrong* by the standard but its behaviour
                (iterator is const) is exactly the right practical answer for me.

                It just saved the OP hours of endless problems.

                It would be better to have an implementation of a set that allows you to
                "re-insert" an object rather than an erase and insert but the API for
                STL containers seem to avoid allowing those kinds of more efficient (yep
                more complex) uses of containers. So you end up placing those
                complications in the application.


                Comment

                • Jerry Coffin

                  #9
                  Re: g++ const 'this' problems

                  In article <bs2akc$c7c@dis patch.concentri c.net>, gi2nospam@maria ni.ws
                  says...

                  [ ... ]
                  [color=blue]
                  > Strictly speaking, you're 100% correct, however, in any case, gcc
                  > behaviour is probably is *wrong* by the standard but its behaviour
                  > (iterator is const) is exactly the right practical answer for me.[/color]

                  Right -- that's exactly why I said it was open to argument instead of
                  saying something like "No, VC7 is right and gcc is wrong." The reality
                  is that pretty much everybody agrees that the standard is wrong the way
                  it stands, but it's still pretty hard for me to condemn somebody for
                  following the standard.

                  The same situation arises (in reverse) with exception specifications: as
                  specified, exception specifications are flawed to the point that
                  enforcing them is really a bad idea. VC++ will give you a warning in a
                  case like this:

                  void junk() throw() { throw 1; }

                  where it can show by static analysis that the code throws an exception
                  it says it won't. OTOH, it does NOT do the run-time enforcement that
                  causes the real problem. In this case, gcc is the one that follows the
                  standard (by calling unexpected() in this case) even though it's pretty
                  clearly the wrong thing to do.

                  In the end, there's no obvious, clear-cut way to handle things like this
                  -- especially when there's usually some room for argument that the way
                  the standard specifies things does have at least some minimal advantage.
                  In the case of modifying the key in a set, if you're SURE your change in
                  the key won't alter the order of elements in the set, then it's fastest
                  to modify it in place. Likewise, calls to unexpected() are likely to
                  help you find incorrect exceptions being thrown fairly quickly -- if
                  you're certain your testing will turn up all the problems before the
                  code is released, it _might_ work out reasonably well (from my comments
                  above, you can probably guess that I consider that unlikely at best).

                  --
                  Later,
                  Jerry.

                  The universe is a figment of its own imagination.

                  Comment

                  • John Calcote

                    #10
                    Re: g++ const 'this' problems

                    tom_usenet <tom_usenet@hot mail.com> wrote in message news:<1o37uv4cr p5lskinrctrvume cup1n98tud@4ax. com>...[color=blue]
                    > On 19 Dec 2003 14:27:10 -0800, jcalcote@novell .com (John Calcote)
                    > wrote:
                    >
                    > It seems GCC is ahead of the game, already having implemented this
                    > defect report:
                    > http://std.dkuug.dk/jtc1/sc22/wg21/d...fects.html#103[/color]

                    Tom (and everyone),

                    Thanks for the concise responses to my question. I now thoroughly
                    understand the problem domain. IMHO, Microsoft's approach to this
                    problem in the standard is more useful, if not necessarily more
                    correct.

                    As a programmer, I understand the fundamental concept of a set. It
                    would not occur to me to try to modify the key data in a set element
                    while it was in the set. While I could see doing this accidentally, I
                    don't necessarily think a compiler or library should prevent me from
                    doing it, because such precautions also prevent me from doing
                    reasonable things with set elements - such as changing non-key data.

                    As a side note, before I posted this message, I had changed Bind to
                    const, and then marked the data members touched by Bind as mutable. I
                    don't like this "solution" at all because frankly, it's nothing short
                    of casting away const on 'this', which lacks elegance, and generally
                    indicates design flaws. It's a hack required to accomplish something
                    entirely legitimate, and made necessary by an overbearing constraint.
                    Such constraints go against the grain of the original C and C++
                    language goals (remember the "shoot yourself in the foot" analogies
                    that used to float around years ago?)

                    In any case, I think I'll switch container types because my code has
                    to be portable to Windows, NetWare and 5 flavors of Unix. I can't take
                    a chance that a different interpretation of the standard in this area
                    will cause some future port to fail in a way that I can foresee and
                    prevent.

                    John

                    Comment

                    Working...