1

I am using Visual Studio 2013 to compile very simple code:

std::set<int> a{ 1, 2, 3 };
std::remove(a.begin(), a.end(), 3);

I expect this can't go wrong but I am surprised. Error emits:

Error   1   error C3892: '_Next' : you cannot assign to a variable that is const    c:\program files (x86)\microsoft visual studio 12.0\vc\include\algorithm

How could this be? a is a non-const std::set. std::remove() moves the element of it and seems perfectly legal.

In VS 2008, below similar code compiles with no error:

std::set<int> a;
std::remove(a.begin(), a.end(), 3);
Sheen
  • 3,333
  • 5
  • 26
  • 46

2 Answers2

4

The set is non-const but set::begin(), set::end() returns a const_iterator. As can be seen on cppreference.

I believe this is to avoid "outsiders" being able to swap elements around as one of set's invariants is that all elements are sorted (this is exactly what std::remove does, it moves elements around so that you can call erase on it afterwards, see erase-remove idiom)

If you want to remove an element use erase member function.

Borgleader
  • 15,826
  • 5
  • 46
  • 62
  • Yes, I notice this behaviour. It is different from VS 2008. In VS 2008, the code compiles. – Sheen May 14 '15 at 15:39
  • @Sheen this is a change in the C++ standard itself. – Mark Ransom May 14 '15 at 15:39
  • P.S. I'm not fond of the change. You used to be able to make an object with a key part, and as long as you didn't change the key you could modify the rest of the object as necessary. That's no longer allowed. – Mark Ransom May 14 '15 at 15:44
  • @MarkRansom - What change? All the compilers I use reject `std::remove(a.begin(), a.end(), 3)`, regardless of the version of the standard I tell the compiler to compile against. I suspect it's more of a case that VS 2008 (a compiler I don't use) wasn't compliant with any version of the standard. – David Hammen May 14 '15 at 15:58
  • @DavidHammen I suppose it's possible that I'm remembering incorrectly. All I know is that I've used that pattern a couple of times and I was sorry to see it go. – Mark Ransom May 14 '15 at 16:10
0

std::remove is intended for linear containers like vector and list, not sorted containers like set. (Consider: remove swaps elements. What would it even mean to swap elements of a set?)

It sounds like you want std::set::erase.

Sneftel
  • 40,271
  • 12
  • 71
  • 104