9

The following code:

#include <iostream>
#include <set>
#include <algorithm>

std::set<int> s;

int main()
{
    s.insert(1);
    s.insert(2);

    std::remove(s.begin(), s.end(), 1);
}

does not compile with gcc 4.7.2:

$ LANG=C g++ test.cpp
In file included from /usr/include/c++/4.7/algorithm:63:0,
             from test.cpp:3:
/usr/include/c++/4.7/bits/stl_algo.h: In instantiation of '_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = std::_Rb_tree_const_iterator<int>; _Tp = int]':
test.cpp:12:38:   required from here
/usr/include/c++/4.7/bits/stl_algo.h:1135:13: error: assignment of read-only location '__result.std::_Rb_tree_const_iterator<_Tp>::operator*<int>()'

So I went to the definition of fset::iterator and I've found this in gcc's implementation (file ../c++/4.7/bits/stl_set.h, from 125):

  // _GLIBCXX_RESOLVE_LIB_DEFECTS                                                                                                                                                             
  // DR 103. set::iterator is required to be modifiable,                                                                                                                                      
  // but this allows modification of keys.                                                                                                                                                    
  typedef typename _Rep_type::const_iterator            iterator;
  typedef typename _Rep_type::const_iterator            const_iterator;
  typedef typename _Rep_type::const_reverse_iterator    reverse_iterator;
  typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
  typedef typename _Rep_type::size_type                 size_type;
  typedef typename _Rep_type::difference_type           difference_type;

Why are both definitions constant? Why does my (pretty simple) code not work?

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
ABu
  • 10,423
  • 6
  • 52
  • 103
  • what are you trying to do? To remove a single element just use erase http://www.cplusplus.com/reference/set/set/erase/ – marcadian Apr 27 '13 at 22:36
  • 5
    There is a trick in the name: `remove` doesn't remove elements. It moves them to the end of the range. This is outright impossible with an ordered container. – pmr Apr 27 '13 at 22:43
  • @marcadian This is only an example to illustrate my problem. My real problem involve more code, with `remove_if` and a predicate, but the problem is the same. – ABu Apr 27 '13 at 22:49

1 Answers1

18

std::set is ordered container, while std::remove changes order of elements in container placing elements that should be removed to the end, thus it can't be used with ordered containers where elements order is defined by predicate. You need to use:

s.erase( 1);

To remove 1 from set.

alexrider
  • 4,449
  • 1
  • 17
  • 27