Abusing const/mutable with std::set

Discussion in 'C++' started by esuvs81@googlemail.com, Oct 4, 2007.

  1. Guest

    Hi Guys,

    I wish to modify some values of items contained in a set after they
    have been added. However, the Jossutis book tells me:

    "...from an iterator's point of view, all element are considered
    constant. This is necessary to ensure that you can't compromise the
    order of the elements by changing their values."

    I accept this makes sense - however I have provided custom comparison
    operators and I know that the values I want to change are not used by
    these comparison operators - hence changing them shouldn't affect the
    ordering.

    To give a concrete example, my objects are actually 3d vertices
    containing a position and a normal. Comparisons are performed using
    only the position. I throw a whole bunch of vertices into the set,
    duplicates get eliminated, and I compute normals for only those that
    survive. This means modifying normals for vertices which are already
    in the set.

    Visual C++ is actually fine with this, but GCC complains that my
    'setNormal()' function is non-const but is being called on a const
    object. So I make 'setNormal()' a const function, which in turn means
    making the normal variable mutable so it can still be changed.

    This all appears to work, but I basically concerned that there might
    be some unexpected side effect which might get me later. I'm aware
    that I've bent the rules of mutable in that I have caused an
    observable change to my object (other bits of code will use the normal
    later) but the extent is relatively limited. How acceptable is this?
    And are there other reasons the items should be treated as const,
    besides the ordering?

    Thanks for any input!

    David
    , Oct 4, 2007
    #1
    1. Advertising

  2. wrote:
    > I wish to modify some values of items contained in a set after they
    > have been added. [..] How acceptable is this?
    > And are there other reasons the items should be treated as const,
    > besides the ordering?


    No, there are no other reasons. However, to be entirely correct,
    you should perhaps consider storing the iterator following the item
    you're trying to change, remove the item, change it, and then insert
    it again using the stored iterator as the hint. It will be constant
    AFA the complexity is concerned. And you'll have no mutable members
    in your structs... Try it.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Oct 4, 2007
    #2
    1. Advertising

  3. Guest

    On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    > wrote:
    > > I wish to modify some values of items contained in a set after they
    > > have been added. [..] How acceptable is this?
    > > And are there other reasons the items should be treated as const,
    > > besides the ordering?

    >
    > No, there are no other reasons. However, to be entirely correct,
    > you should perhaps consider storing the iterator following the item
    > you're trying to change, remove the item, change it, and then insert
    > it again using the stored iterator as the hint. It will be constant
    > AFA the complexity is concerned. And you'll have no mutable members
    > in your structs... Try it.
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    Ok, thanks for the quick reply. I will look into removing and
    reinserting the object - my only concern is that other iterators may
    be pointing at it (in my triangle and mesh classes). If I remove and
    reinsert it then it will be at the same point in the sequence, but I
    doubt if this guarantees existing iterators will still be valid.

    Though I can probably change my code so I don't create other iterators
    until the vertex object is finished being set up. I'll have a look...

    Thanks for the help anyway :-D
    , Oct 4, 2007
    #3
  4. wrote:
    > On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    >> wrote:
    >>> I wish to modify some values of items contained in a set after they
    >>> have been added. [..] How acceptable is this?
    >>> And are there other reasons the items should be treated as const,
    >>> besides the ordering?

    >>
    >> No, there are no other reasons. However, to be entirely correct,
    >> you should perhaps consider storing the iterator following the item
    >> you're trying to change, remove the item, change it, and then insert
    >> it again using the stored iterator as the hint. It will be constant
    >> AFA the complexity is concerned. And you'll have no mutable members
    >> in your structs... Try it.
    >>
    >> V
    >> --
    >> Please remove capital 'A's when replying by e-mail
    >> I do not respond to top-posted replies, please don't ask

    >
    > Ok, thanks for the quick reply. I will look into removing and
    > reinserting the object - my only concern is that other iterators may
    > be pointing at it (in my triangle and mesh classes). If I remove and
    > reinsert it then it will be at the same point in the sequence, but I
    > doubt if this guarantees existing iterators will still be valid.


    That's a valid concern. Most likely they will become invalid.

    > Though I can probably change my code so I don't create other iterators
    > until the vertex object is finished being set up. I'll have a look...


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Oct 4, 2007
    #4
  5. terminator Guest

    On Oct 4, 6:48 pm, "Victor Bazarov" <> wrote:
    > wrote:
    > > On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    > >> wrote:
    > >>> I wish to modify some values of items contained in a set after they
    > >>> have been added. [..] How acceptable is this?
    > >>> And are there other reasons the items should be treated as const,
    > >>> besides the ordering?

    >
    > >> No, there are no other reasons. However, to be entirely correct,
    > >> you should perhaps consider storing the iterator following the item
    > >> you're trying to change, remove the item, change it, and then insert
    > >> it again using the stored iterator as the hint. It will be constant
    > >> AFA the complexity is concerned. And you'll have no mutable members
    > >> in your structs... Try it.

    >
    > >> V
    > >> --
    > >> Please remove capital 'A's when replying by e-mail
    > >> I do not respond to top-posted replies, please don't ask

    >
    > > Ok, thanks for the quick reply. I will look into removing and
    > > reinserting the object - my only concern is that other iterators may
    > > be pointing at it (in my triangle and mesh classes). If I remove and
    > > reinsert it then it will be at the same point in the sequence, but I
    > > doubt if this guarantees existing iterators will still be valid.

    >
    > That's a valid concern. Most likely they will become invalid.
    >
    > > Though I can probably change my code so I don't create other iterators
    > > until the vertex object is finished being set up. I'll have a look...

    >
    > V


    wrap it:

    class my_data;
    class const_remover{
    mutable my_data data;
    //define ctor(s)
    };

    class my_alloc:
    std::allocator<const_remover>
    {
    //redefine:
    class value_type;
    class reference_type;
    class pointer_type;
    };

    class my_comp;

    typedef set<const_remover,my_comp,my_alloc> my_set;


    regards,
    FM.
    terminator, Oct 4, 2007
    #5
  6. Mark P Guest

    wrote:
    > Hi Guys,
    >
    > I wish to modify some values of items contained in a set after they
    > have been added. However, the Jossutis book tells me:
    >
    > "...from an iterator's point of view, all element are considered
    > constant. This is necessary to ensure that you can't compromise the
    > order of the elements by changing their values."
    >
    > I accept this makes sense - however I have provided custom comparison
    > operators and I know that the values I want to change are not used by
    > these comparison operators - hence changing them shouldn't affect the
    > ordering.
    >
    > To give a concrete example, my objects are actually 3d vertices
    > containing a position and a normal. Comparisons are performed using
    > only the position. I throw a whole bunch of vertices into the set,
    > duplicates get eliminated, and I compute normals for only those that
    > survive. This means modifying normals for vertices which are already
    > in the set.
    >
    > Visual C++ is actually fine with this, but GCC complains that my
    > 'setNormal()' function is non-const but is being called on a const
    > object. So I make 'setNormal()' a const function, which in turn means
    > making the normal variable mutable so it can still be changed.
    >
    > This all appears to work, but I basically concerned that there might
    > be some unexpected side effect which might get me later. I'm aware
    > that I've bent the rules of mutable in that I have caused an
    > observable change to my object (other bits of code will use the normal
    > later) but the extent is relatively limited. How acceptable is this?
    > And are there other reasons the items should be treated as const,
    > besides the ordering?
    >
    > Thanks for any input!
    >
    > David
    >


    Another option is to store pointers in your set, modify the only the
    targets of the pointers rather than the pointers themselves, and define
    your comparison function to dereference these poitners before doing its
    usual operation.

    My feeling is that what you're doing is error-prone but probably safe if
    done correctly. A couple years ago I did something similar but, rather
    than modifying the objects in the set, I modified the comparison
    function used by the set. This was to implement a sweep line algorithm
    where the comparison depends upon the sweep line position. It worked
    like a charm, with the requirement that changing the functor must not
    change the ordering of any elements in the set.

    -Mark
    Mark P, Oct 4, 2007
    #6
  7. Jim Langston Guest

    "terminator" <> wrote in message
    news:...
    > On Oct 4, 6:48 pm, "Victor Bazarov" <> wrote:
    >> wrote:
    >> > On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    >> >> wrote:
    >> >>> I wish to modify some values of items contained in a set after they
    >> >>> have been added. [..] How acceptable is this?
    >> >>> And are there other reasons the items should be treated as const,
    >> >>> besides the ordering?

    >>
    >> >> No, there are no other reasons. However, to be entirely correct,
    >> >> you should perhaps consider storing the iterator following the item
    >> >> you're trying to change, remove the item, change it, and then insert
    >> >> it again using the stored iterator as the hint. It will be constant
    >> >> AFA the complexity is concerned. And you'll have no mutable members
    >> >> in your structs... Try it.

    >>
    >> >> V
    >> >> --
    >> >> Please remove capital 'A's when replying by e-mail
    >> >> I do not respond to top-posted replies, please don't ask

    >>
    >> > Ok, thanks for the quick reply. I will look into removing and
    >> > reinserting the object - my only concern is that other iterators may
    >> > be pointing at it (in my triangle and mesh classes). If I remove and
    >> > reinsert it then it will be at the same point in the sequence, but I
    >> > doubt if this guarantees existing iterators will still be valid.

    >>
    >> That's a valid concern. Most likely they will become invalid.
    >>
    >> > Though I can probably change my code so I don't create other iterators
    >> > until the vertex object is finished being set up. I'll have a look...

    >>
    >> V

    >
    > wrap it:
    >
    > class my_data;
    > class const_remover{
    > mutable my_data data;
    > //define ctor(s)
    > };
    >
    > class my_alloc:
    > std::allocator<const_remover>
    > {
    > //redefine:
    > class value_type;
    > class reference_type;
    > class pointer_type;
    > };
    >
    > class my_comp;
    >
    > typedef set<const_remover,my_comp,my_alloc> my_set;


    Is VC++ .net 2003 non standard compliant as far as set goes then? This
    compiled and runs, and according to this discussion it shouldn't. I was
    planning on seeing what chaning i to mutable would do, but it runs with or
    without it being mutable.

    #include <iostream>
    #include <string>
    #include <set>

    class Foo
    {
    public:
    double x, y, z;
    double i;
    };

    bool operator<( const Foo& lhs, const Foo& rhs )
    {
    if ( lhs.x < rhs.x )
    return true;
    else if ( lhs.x == rhs.x )
    if ( lhs.y < rhs.y )
    return true;
    else if ( lhs.y == rhs.y )
    if ( lhs.z < rhs.z )
    return true;
    return false;
    }


    int main()
    {
    std::set<Foo> Bar;

    Foo Inst;
    Inst.x = 1.0;
    Inst.y = 2.0;
    Inst.z = 3.0;
    Inst.i = 1234.0;

    Bar.insert( Inst );
    std::set<Foo>::iterator it = Bar.find( Inst );
    it->i = 5.0;
    it->x = 7.0;

    for ( std::set<Foo>::iterator it = Bar.begin(); it != Bar.end(); ++it )
    {
    std::cout << it->x << " " << it->y << " " << it->z << " " << it->i
    << "\n";
    }

    return 0;
    }
    Jim Langston, Oct 4, 2007
    #7
  8. Guest

    On 4 Oct, 19:38, "Jim Langston" <> wrote:
    > "terminator" <> wrote in message
    >
    > news:...
    >
    >
    >
    > > On Oct 4, 6:48 pm, "Victor Bazarov" <> wrote:
    > >> wrote:
    > >> > On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    > >> >> wrote:
    > >> >>> I wish to modify some values of items contained in a set after they
    > >> >>> have been added. [..] How acceptable is this?
    > >> >>> And are there other reasons the items should be treated as const,
    > >> >>> besides the ordering?

    >
    > >> >> No, there are no other reasons. However, to be entirely correct,
    > >> >> you should perhaps consider storing the iterator following the item
    > >> >> you're trying to change, remove the item, change it, and then insert
    > >> >> it again using the stored iterator as the hint. It will be constant
    > >> >> AFA the complexity is concerned. And you'll have no mutable members
    > >> >> in your structs... Try it.

    >
    > >> >> V
    > >> >> --
    > >> >> Please remove capital 'A's when replying by e-mail
    > >> >> I do not respond to top-posted replies, please don't ask

    >
    > >> > Ok, thanks for the quick reply. I will look into removing and
    > >> > reinserting the object - my only concern is that other iterators may
    > >> > be pointing at it (in my triangle and mesh classes). If I remove and
    > >> > reinsert it then it will be at the same point in the sequence, but I
    > >> > doubt if this guarantees existing iterators will still be valid.

    >
    > >> That's a valid concern. Most likely they will become invalid.

    >
    > >> > Though I can probably change my code so I don't create other iterators
    > >> > until the vertex object is finished being set up. I'll have a look...

    >
    > >> V

    >
    > > wrap it:

    >
    > > class my_data;
    > > class const_remover{
    > > mutable my_data data;
    > > //define ctor(s)
    > > };

    >
    > > class my_alloc:
    > > std::allocator<const_remover>
    > > {
    > > //redefine:
    > > class value_type;
    > > class reference_type;
    > > class pointer_type;
    > > };

    >
    > > class my_comp;

    >
    > > typedef set<const_remover,my_comp,my_alloc> my_set;

    >
    > Is VC++ .net 2003 non standard compliant as far as set goes then? This
    > compiled and runs, and according to this discussion it shouldn't. I was
    > planning on seeing what chaning i to mutable would do, but it runs with or
    > without it being mutable.
    >
    > #include <iostream>
    > #include <string>
    > #include <set>
    >
    > class Foo
    > {
    > public:
    > double x, y, z;
    > double i;
    >
    > };
    >
    > bool operator<( const Foo& lhs, const Foo& rhs )
    > {
    > if ( lhs.x < rhs.x )
    > return true;
    > else if ( lhs.x == rhs.x )
    > if ( lhs.y < rhs.y )
    > return true;
    > else if ( lhs.y == rhs.y )
    > if ( lhs.z < rhs.z )
    > return true;
    > return false;
    >
    > }
    >
    > int main()
    > {
    > std::set<Foo> Bar;
    >
    > Foo Inst;
    > Inst.x = 1.0;
    > Inst.y = 2.0;
    > Inst.z = 3.0;
    > Inst.i = 1234.0;
    >
    > Bar.insert( Inst );
    > std::set<Foo>::iterator it = Bar.find( Inst );
    > it->i = 5.0;
    > it->x = 7.0;
    >
    > for ( std::set<Foo>::iterator it = Bar.begin(); it != Bar.end(); ++it )
    > {
    > std::cout << it->x << " " << it->y << " " << it->z << " " << it->i
    > << "\n";
    > }
    >
    > return 0;
    >
    > }


    Under GCC, I get the following error with your code:

    david@localhost:~$ g++ test.cpp
    test.cpp: In function int main():
    test.cpp:39: error: assignment of data-member Foo::i in read-only
    structure
    test.cpp:40: error: assignment of data-member Foo::x in read-only
    structure

    which corresponds to the lines:

    it->i = 5.0;
    it->x = 7.0;

    However, my interpretation of the Josuttis book is not that you can't
    do it, but that you shouldn't do it. I suspect that find(), begin(),
    etc would like to return a const_iterator but that they are required
    to return a non-const version in order to be compliant with the rest
    of the STL. Though I don't know how GCC knows that the data structure
    is read only.
    , Oct 4, 2007
    #8
  9. Guest

    On 4 Oct, 19:01, Mark P <> wrote:
    > wrote:
    > > Hi Guys,

    >
    > > I wish to modify some values of items contained in a set after they
    > > have been added. However, the Jossutis book tells me:

    >
    > > "...from an iterator's point of view, all element are considered
    > > constant. This is necessary to ensure that you can't compromise the
    > > order of the elements by changing their values."

    >
    > > I accept this makes sense - however I have provided custom comparison
    > > operators and I know that the values I want to change are not used by
    > > these comparison operators - hence changing them shouldn't affect the
    > > ordering.

    >
    > > To give a concrete example, my objects are actually 3d vertices
    > > containing a position and a normal. Comparisons are performed using
    > > only the position. I throw a whole bunch of vertices into the set,
    > > duplicates get eliminated, and I compute normals for only those that
    > > survive. This means modifying normals for vertices which are already
    > > in the set.

    >
    > > Visual C++ is actually fine with this, but GCC complains that my
    > > 'setNormal()' function is non-const but is being called on a const
    > > object. So I make 'setNormal()' a const function, which in turn means
    > > making the normal variable mutable so it can still be changed.

    >
    > > This all appears to work, but I basically concerned that there might
    > > be some unexpected side effect which might get me later. I'm aware
    > > that I've bent the rules of mutable in that I have caused an
    > > observable change to my object (other bits of code will use the normal
    > > later) but the extent is relatively limited. How acceptable is this?
    > > And are there other reasons the items should be treated as const,
    > > besides the ordering?

    >
    > > Thanks for any input!

    >
    > > David

    >
    > Another option is to store pointers in your set, modify the only the
    > targets of the pointers rather than the pointers themselves, and define
    > your comparison function to dereference these poitners before doing its
    > usual operation.


    Hmmm... that could work but it get a bit more complicated. I'll have
    to think about it!

    > My feeling is that what you're doing is error-prone but probably safe if
    > done correctly.


    That's pretty much my feeling :-D I'll certainly have to hide this
    stuff from the public API.
    , Oct 4, 2007
    #9
  10. On Thu, 04 Oct 2007 14:09:02 +0000, esuvs81 wrote:
    > Hi Guys,
    >
    > I wish to modify some values of items contained in a set after they have
    > been added. However, the Jossutis book tells me:
    >
    > "...from an iterator's point of view, all element are considered
    > constant. This is necessary to ensure that you can't compromise the
    > order of the elements by changing their values."
    >
    > I accept this makes sense - however I have provided custom comparison
    > operators and I know that the values I want to change are not used by
    > these comparison operators - hence changing them shouldn't affect the
    > ordering.
    >


    [snip]

    >
    > Visual C++ is actually fine with this, but GCC complains that my
    > 'setNormal()' function is non-const but is being called on a const
    > object. So I make 'setNormal()' a const function, which in turn means
    > making the normal variable mutable so it can still be changed.


    Visual C++ is compliant with the current C++ standard (2003) in this
    respect -- GCC is not. There is however a defect report that has made it
    into the working paper of the upcoming new standard which will change
    things around.

    So eventually your code will very likely become illegal.

    --
    Markus Schoder
    Markus Schoder, Oct 4, 2007
    #10
  11. Guest

    On 4 Oct, 22:01, Markus Schoder <> wrote:
    > On Thu, 04 Oct 2007 14:09:02 +0000, esuvs81 wrote:
    > > Hi Guys,

    >
    > > I wish to modify some values of items contained in a set after they have
    > > been added. However, the Jossutis book tells me:

    >
    > > "...from an iterator's point of view, all element are considered
    > > constant. This is necessary to ensure that you can't compromise the
    > > order of the elements by changing their values."

    >
    > > I accept this makes sense - however I have provided custom comparison
    > > operators and I know that the values I want to change are not used by
    > > these comparison operators - hence changing them shouldn't affect the
    > > ordering.

    >
    > [snip]
    >
    >
    >
    > > Visual C++ is actually fine with this, but GCC complains that my
    > > 'setNormal()' function is non-const but is being called on a const
    > > object. So I make 'setNormal()' a const function, which in turn means
    > > making the normal variable mutable so it can still be changed.

    >
    > Visual C++ is compliant with the current C++ standard (2003) in this
    > respect -- GCC is not. There is however a defect report that has made it
    > into the working paper of the upcoming new standard which will change
    > things around.
    >
    > So eventually your code will very likely become illegal.
    >
    > --
    > Markus Schoder


    That's worth knowing - but you say GCC it compatible with the new way
    of doing things? Such that the mutable 'hack' I've use to get it
    running on GCC will still be valid?
    , Oct 4, 2007
    #11
  12. Guest

    On 4 Oct, 18:40, terminator <> wrote:
    > On Oct 4, 6:48 pm, "Victor Bazarov" <> wrote:
    >
    >
    >
    > > wrote:
    > > > On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    > > >> wrote:
    > > >>> I wish to modify some values of items contained in a set after they
    > > >>> have been added. [..] How acceptable is this?
    > > >>> And are there other reasons the items should be treated as const,
    > > >>> besides the ordering?

    >
    > > >> No, there are no other reasons. However, to be entirely correct,
    > > >> you should perhaps consider storing the iterator following the item
    > > >> you're trying to change, remove the item, change it, and then insert
    > > >> it again using the stored iterator as the hint. It will be constant
    > > >> AFA the complexity is concerned. And you'll have no mutable members
    > > >> in your structs... Try it.

    >
    > > >> V
    > > >> --
    > > >> Please remove capital 'A's when replying by e-mail
    > > >> I do not respond to top-posted replies, please don't ask

    >
    > > > Ok, thanks for the quick reply. I will look into removing and
    > > > reinserting the object - my only concern is that other iterators may
    > > > be pointing at it (in my triangle and mesh classes). If I remove and
    > > > reinsert it then it will be at the same point in the sequence, but I
    > > > doubt if this guarantees existing iterators will still be valid.

    >
    > > That's a valid concern. Most likely they will become invalid.

    >
    > > > Though I can probably change my code so I don't create other iterators
    > > > until the vertex object is finished being set up. I'll have a look...

    >
    > > V

    >
    > wrap it:
    >
    > class my_data;
    > class const_remover{
    > mutable my_data data;
    > //define ctor(s)
    >
    > };
    >
    > class my_alloc:
    > std::allocator<const_remover>
    > {
    > //redefine:
    > class value_type;
    > class reference_type;
    > class pointer_type;
    >
    > };
    >
    > class my_comp;
    >
    > typedef set<const_remover,my_comp,my_alloc> my_set;
    >
    > regards,
    > FM.


    I'm sorry, you're idea sounds interesting but I don't have much
    understanding of allocators. As I understand it you're addressing my
    second problem - that if I remove an item and then reinsert it that it
    might end up in a different location in memory. You're suggesting I
    can control this behaviour with a custom allocator? Sounds sensible,
    but can you explain what you mean by redefining the types? Presumably
    there needs to be more to the my_alloc class than what you have shown?
    Thanks for the help!
    , Oct 4, 2007
    #12
  13. On Thu, 04 Oct 2007 21:25:07 +0000, esuvs81 wrote:
    > On 4 Oct, 22:01, Markus Schoder <> wrote:
    >> On Thu, 04 Oct 2007 14:09:02 +0000, esuvs81 wrote:
    >> > Visual C++ is actually fine with this, but GCC complains that my
    >> > 'setNormal()' function is non-const but is being called on a const
    >> > object. So I make 'setNormal()' a const function, which in turn means
    >> > making the normal variable mutable so it can still be changed.

    >>
    >> Visual C++ is compliant with the current C++ standard (2003) in this
    >> respect -- GCC is not. There is however a defect report that has made
    >> it into the working paper of the upcoming new standard which will
    >> change things around.
    >>
    >> So eventually your code will very likely become illegal.
    >>

    > That's worth knowing - but you say GCC it compatible with the new way of
    > doing things? Such that the mutable 'hack' I've use to get it running on
    > GCC will still be valid?


    Yes, your workaround should still work. Sorry for not making this clear.

    --
    Markus Schoder
    Markus Schoder, Oct 5, 2007
    #13
  14. On 2007-10-04 22:12, wrote:
    > On 4 Oct, 19:38, "Jim Langston" <> wrote:
    >> "terminator" <> wrote in message
    >>
    >> news:...
    >>
    >>
    >>
    >> > On Oct 4, 6:48 pm, "Victor Bazarov" <> wrote:
    >> >> wrote:
    >> >> > On 4 Oct, 15:13, "Victor Bazarov" <> wrote:
    >> >> >> wrote:
    >> >> >>> I wish to modify some values of items contained in a set after they
    >> >> >>> have been added. [..] How acceptable is this?
    >> >> >>> And are there other reasons the items should be treated as const,
    >> >> >>> besides the ordering?

    >>
    >> >> >> No, there are no other reasons. However, to be entirely correct,
    >> >> >> you should perhaps consider storing the iterator following the item
    >> >> >> you're trying to change, remove the item, change it, and then insert
    >> >> >> it again using the stored iterator as the hint. It will be constant
    >> >> >> AFA the complexity is concerned. And you'll have no mutable members
    >> >> >> in your structs... Try it.

    >>
    >> >> >> V
    >> >> >> --
    >> >> >> Please remove capital 'A's when replying by e-mail
    >> >> >> I do not respond to top-posted replies, please don't ask

    >>
    >> >> > Ok, thanks for the quick reply. I will look into removing and
    >> >> > reinserting the object - my only concern is that other iterators may
    >> >> > be pointing at it (in my triangle and mesh classes). If I remove and
    >> >> > reinsert it then it will be at the same point in the sequence, but I
    >> >> > doubt if this guarantees existing iterators will still be valid.

    >>
    >> >> That's a valid concern. Most likely they will become invalid.

    >>
    >> >> > Though I can probably change my code so I don't create other iterators
    >> >> > until the vertex object is finished being set up. I'll have a look...

    >>
    >> >> V

    >>
    >> > wrap it:

    >>
    >> > class my_data;
    >> > class const_remover{
    >> > mutable my_data data;
    >> > //define ctor(s)
    >> > };

    >>
    >> > class my_alloc:
    >> > std::allocator<const_remover>
    >> > {
    >> > //redefine:
    >> > class value_type;
    >> > class reference_type;
    >> > class pointer_type;
    >> > };

    >>
    >> > class my_comp;

    >>
    >> > typedef set<const_remover,my_comp,my_alloc> my_set;

    >>
    >> Is VC++ .net 2003 non standard compliant as far as set goes then? This
    >> compiled and runs, and according to this discussion it shouldn't. I was
    >> planning on seeing what chaning i to mutable would do, but it runs with or
    >> without it being mutable.
    >>
    >> #include <iostream>
    >> #include <string>
    >> #include <set>
    >>
    >> class Foo
    >> {
    >> public:
    >> double x, y, z;
    >> double i;
    >>
    >> };
    >>
    >> bool operator<( const Foo& lhs, const Foo& rhs )
    >> {
    >> if ( lhs.x < rhs.x )
    >> return true;
    >> else if ( lhs.x == rhs.x )
    >> if ( lhs.y < rhs.y )
    >> return true;
    >> else if ( lhs.y == rhs.y )
    >> if ( lhs.z < rhs.z )
    >> return true;
    >> return false;
    >>
    >> }
    >>
    >> int main()
    >> {
    >> std::set<Foo> Bar;
    >>
    >> Foo Inst;
    >> Inst.x = 1.0;
    >> Inst.y = 2.0;
    >> Inst.z = 3.0;
    >> Inst.i = 1234.0;
    >>
    >> Bar.insert( Inst );
    >> std::set<Foo>::iterator it = Bar.find( Inst );
    >> it->i = 5.0;
    >> it->x = 7.0;
    >>
    >> for ( std::set<Foo>::iterator it = Bar.begin(); it != Bar.end(); ++it )
    >> {
    >> std::cout << it->x << " " << it->y << " " << it->z << " " << it->i
    >> << "\n";
    >> }
    >>
    >> return 0;
    >>
    >> }

    >
    > Under GCC, I get the following error with your code:
    >
    > david@localhost:~$ g++ test.cpp
    > test.cpp: In function int main():
    > test.cpp:39: error: assignment of data-member Foo::i in read-only
    > structure
    > test.cpp:40: error: assignment of data-member Foo::x in read-only
    > structure
    >
    > which corresponds to the lines:
    >
    > it->i = 5.0;
    > it->x = 7.0;
    >
    > However, my interpretation of the Josuttis book is not that you can't
    > do it, but that you shouldn't do it. I suspect that find(), begin(),
    > etc would like to return a const_iterator but that they are required
    > to return a non-const version in order to be compliant with the rest
    > of the STL. Though I don't know how GCC knows that the data structure
    > is read only.


    set needs to make sure that it is always sorted, meaning that any
    operation on its elements which might affect the sorting must be
    disallowed. However the compiler can not know which members of the
    elements that are taken into account when sorting (or how) so the set
    must disallow all modifications of its elements. In the implementation
    that comes with VC++ the set iterator is implemented by inheriting from
    the const_iterator.

    --
    Erik Wikström
    =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=, Oct 5, 2007
    #14
  15. James Kanze Guest

    On Oct 4, 8:38 pm, "Jim Langston" <> wrote:
    > "terminator" <> wrote in message
    > news:...


    [...]
    > Is VC++ .net 2003 non standard compliant as far as set goes then?


    Possibly. This touches on a much debated point, where members
    of the committee didn't really agree. On one hand, of course,
    allowing modification allows changes that would affect the
    order, and thus invalidate the set. On the other, a lot of
    people wanted to use set more or less like a data base, with
    it's primary index, i.e. they provided an indexation function
    which only considered one (immutable) field of a large structure
    of data. In the end, the arguments for safety won out, and the
    standard says that both set::iterator and set::const_iterator
    are constant iterators, i.e. that neither allow modification of
    the pointed to object. Many implementations had already been
    shipped, however, which did allow modification. (I think that
    the original Stepanov implementation allowed it.) And
    understandably, vendors are reluctant to break existing code,
    and since any code which is conformant with the standard still
    works, they probably don't feel much preasure to change.

    There are any number of work-arounds. The one time I made
    extensive use of std::set, they contained pointers to the actual
    objects; I removed and reinserted anyway, because my
    modifications did affect the ordering criteria. The official
    line, of course, is to use a map, but in a case like that of the
    original poster, that would mean either breaking up his
    structure in the map, or duplicating 3/4ths of the data (with
    the risk that the duplicate somehow end up not being the same).
    In his case, I think I'd just use a const_cast on the results of
    dereferencing the iterator:
    const_cast< double& >( iter->normal ) = ...
    Elegant it's not, but it works.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 5, 2007
    #15
  16. James Kanze Guest

    On Oct 4, 11:01 pm, Markus Schoder <> wrote:
    > On Thu, 04 Oct 2007 14:09:02 +0000, esuvs81 wrote:
    > > I wish to modify some values of items contained in a set after they have
    > > been added. However, the Jossutis book tells me:


    > > "...from an iterator's point of view, all element are considered
    > > constant. This is necessary to ensure that you can't compromise the
    > > order of the elements by changing their values."


    > > I accept this makes sense - however I have provided custom comparison
    > > operators and I know that the values I want to change are not used by
    > > these comparison operators - hence changing them shouldn't affect the
    > > ordering.


    > [snip]
    > > Visual C++ is actually fine with this, but GCC complains that my
    > > 'setNormal()' function is non-const but is being called on a const
    > > object. So I make 'setNormal()' a const function, which in turn means
    > > making the normal variable mutable so it can still be changed.


    > Visual C++ is compliant with the current C++ standard (2003) in this
    > respect -- GCC is not. There is however a defect report that has made it
    > into the working paper of the upcoming new standard which will change
    > things around.


    The 1998 version of the standard doesn't say one way or another,
    so both VC++ and G++ are correct, depending on how you interpret
    things. The defect report was because this wasn't specified,
    and the resolution only clarified the original intent.
    (Presumably---since that's all resolutions of defect reports are
    supposed to do. In all likelihood, the people actually voting
    on the original standard had different intents. At any rate, I
    do know that there was some disagreement concerning this.)

    > So eventually your code will very likely become illegal.


    A TC is the standard committees way of saying: this is what the
    standard means. So formally, the code is illegal today.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 5, 2007
    #16
  17. On Fri, 05 Oct 2007 10:02:47 +0000, James Kanze wrote:
    > On Oct 4, 11:01 pm, Markus Schoder <> wrote:
    >> On Thu, 04 Oct 2007 14:09:02 +0000, esuvs81 wrote:
    >> > I wish to modify some values of items contained in a set after they
    >> > have been added. However, the Jossutis book tells me:

    >
    >> > "...from an iterator's point of view, all element are considered
    >> > constant. This is necessary to ensure that you can't compromise the
    >> > order of the elements by changing their values."

    >
    >> > I accept this makes sense - however I have provided custom comparison
    >> > operators and I know that the values I want to change are not used by
    >> > these comparison operators - hence changing them shouldn't affect the
    >> > ordering.

    >
    >> [snip]
    >> > Visual C++ is actually fine with this, but GCC complains that my
    >> > 'setNormal()' function is non-const but is being called on a const
    >> > object. So I make 'setNormal()' a const function, which in turn means
    >> > making the normal variable mutable so it can still be changed.

    >
    >> Visual C++ is compliant with the current C++ standard (2003) in this
    >> respect -- GCC is not. There is however a defect report that has made
    >> it into the working paper of the upcoming new standard which will
    >> change things around.

    >
    > The 1998 version of the standard doesn't say one way or another, so both
    > VC++ and G++ are correct, depending on how you interpret things. The
    > defect report was because this wasn't specified, and the resolution only
    > clarified the original intent. (Presumably---since that's all
    > resolutions of defect reports are supposed to do. In all likelihood,
    > the people actually voting on the original standard had different
    > intents. At any rate, I do know that there was some disagreement
    > concerning this.)


    Here we go again... 1998 and 2003 do not differ in that respect. The
    standard is _not_ ambiguous it is not exactly obvious but irrefutable
    that a non const set iterator must allow modification. I will not repeat
    the argument here google it if you want. I have argued it and much
    earlier (but post standard) Herb Sutter has pointed this out too.

    Once the defect report is implemented it will therefore truly change the
    semantics.

    --
    Markus Schoder
    Markus Schoder, Oct 5, 2007
    #17
  18. James Kanze Guest

    On Oct 5, 10:04 pm, Markus Schoder <> wrote:
    > On Fri, 05 Oct 2007 10:02:47 +0000, James Kanze wrote:
    > > On Oct 4, 11:01 pm, Markus Schoder <> wrote:
    > >> On Thu, 04 Oct 2007 14:09:02 +0000, esuvs81 wrote:
    > >> > I wish to modify some values of items contained in a set after they
    > >> > have been added. However, the Jossutis book tells me:


    > >> > "...from an iterator's point of view, all element are considered
    > >> > constant. This is necessary to ensure that you can't compromise the
    > >> > order of the elements by changing their values."


    > >> > I accept this makes sense - however I have provided custom comparison
    > >> > operators and I know that the values I want to change are not used by
    > >> > these comparison operators - hence changing them shouldn't affect the
    > >> > ordering.


    > >> [snip]
    > >> > Visual C++ is actually fine with this, but GCC complains that my
    > >> > 'setNormal()' function is non-const but is being called on a const
    > >> > object. So I make 'setNormal()' a const function, which in turn means
    > >> > making the normal variable mutable so it can still be changed.


    > >> Visual C++ is compliant with the current C++ standard (2003) in this
    > >> respect -- GCC is not. There is however a defect report that has made
    > >> it into the working paper of the upcoming new standard which will
    > >> change things around.


    > > The 1998 version of the standard doesn't say one way or another, so both
    > > VC++ and G++ are correct, depending on how you interpret things. The
    > > defect report was because this wasn't specified, and the resolution only
    > > clarified the original intent. (Presumably---since that's all
    > > resolutions of defect reports are supposed to do. In all likelihood,
    > > the people actually voting on the original standard had different
    > > intents. At any rate, I do know that there was some disagreement
    > > concerning this.)


    > Here we go again... 1998 and 2003 do not differ in that respect. The
    > standard is _not_ ambiguous


    The standards committee voted, and said that there was an error
    in the standard. Formally, a TC is not allowed to change
    anything in the standard, only to clarify.

    > it is not exactly obvious but irrefutable
    > that a non const set iterator must allow modification.


    Well, that's how I'd interpret it, too. But the committee
    actually voted on the thing, and said otherwise. And who are we
    to say that vote was a lie?

    > I will not repeat the argument here google it if you want. I
    > have argued it and much earlier (but post standard) Herb
    > Sutter has pointed this out too.


    > Once the defect report is implemented it will therefore truly
    > change the semantics.


    Formally, I'm afraid, no. The effect of a defect report is more
    or less retroactive: it says that this is what the standard
    actually says. Even if you and I (and Herb Sutter) think it
    says otherwise.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 5, 2007
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Thomas Nelson

    how can I avoid abusing lists?

    Thomas Nelson, Jul 7, 2006, in forum: Python
    Replies:
    16
    Views:
    501
    Jim Segrave
    Jul 8, 2006
  2. Geoffrey S. Knauth
    Replies:
    6
    Views:
    993
    Earl Purple
    Jan 18, 2006
  3. Hapary

    Abusing C/C++ comments

    Hapary, Apr 10, 2007, in forum: C Programming
    Replies:
    28
    Views:
    930
  4. Javier
    Replies:
    2
    Views:
    558
    James Kanze
    Sep 4, 2007
  5. gangesmaster

    abusing exceptions for continuations

    gangesmaster, Dec 10, 2007, in forum: Python
    Replies:
    3
    Views:
    278
    Lautaro Pecile
    Dec 11, 2007
Loading...

Share This Page