0

Since my post from yesterday got down voted, here again, with just the minimal example and my questions.

#include <set>
#include <algorithm>
using namespace std;

class dummy
{
public:
  dummy(int x)
      : test(x)
  {}

  bool operator()(const int &a) const
  {
    return false;
  }

protected:
  int test;
};


void foo()
{

  // Determine the bounding box.
  multiset<float> test;
  test.insert(3.5);
  multiset<float>::iterator itVertex = test.begin();


  multiset<int> workset;
  workset.insert(3);

  for (itVertex = test.begin(); itVertex != test.end(); itVertex++)
  {
    multiset<int>::iterator itEnd = remove_if(workset.begin(), workset.end(), dummy(3));

  }
}

I've tested the example on the two machines: on Linux (Ubuntu 16.04, g++ 5 and 6) I get the previously described error:

/usr/include/c++/5/bits/stl_algo.h:868:23: error: assignment of read-only location ‘__result.std::_Rb_tree_const_iterator<_Tp>::operator*()’ __result = _GLIBCXX_MOVE(__first);

On Windows 7 Visual Studio 2008 it compiles fine.

I've also checked out the duplicates, yet they fail to describe the case where it works on Windows but does not on Linux.

So why does it compile fine on Windows? Why not on Linux? I understand how I can fix the problem itself, but as this is external code, I don't want to edit the code itself if not necessary.

mimre
  • 92
  • 1
  • 9
  • 1
    your post from yesterday was not only downvoted (actually not soo much as to worry about) but it was flagged as a duplicate. Did you read the duplicate? – 463035818_is_not_an_ai Oct 20 '17 at 12:56
  • also being downvoted is no reason to post the same question again...and mentioning it in the first sentence wont prevent you from getting downvotes again (acutally I expect just the opposite) – 463035818_is_not_an_ai Oct 20 '17 at 12:58
  • Yes it was flagged as duplicate, and reading through the duplicate doesn't give the answer to my question: Why does it work on Windows but not on Linux. I understand why it does not work, and that it should not work and how to fix it, the problem is that it still works on the Windows machine without any explanation – mimre Oct 20 '17 at 13:22
  • "does not work"/"does work" is a bit too vague in general. If you break the rules in c++ then "appears to work" is a possible outcome. Why do you want to know why it "works" on windows when you already know that it is wrong? – 463035818_is_not_an_ai Oct 20 '17 at 13:30
  • The reason is, that I'm using the code base of a co-worker who develops on Windows and he does not want to change the base. If I can explain why we need to change this, that would make this argument much easier. Also I'm just curious about the internals in this case. – mimre Oct 20 '17 at 13:31
  • just point him some documentation. Eg [here](http://en.cppreference.com/w/cpp/algorithm/remove) one can read: "These algorithms cannot be used with associative containers such as std::set and std::map because ForwardIt does not dereference to a MoveAssignable type (the keys in these containers are not modifiable) " and maybe do some reasearch on undefined/unspecified behaviour – 463035818_is_not_an_ai Oct 20 '17 at 13:33
  • Thank you for the link, we've been through that. Anyway, we've decided to just adapt the code to make it conform. Thank you for the discussion rather than blindly down voting and flagging as duplicate. – mimre Oct 20 '17 at 13:36

1 Answers1

1

std::remove_if doesn't work with a multiset. It only works with containers which can be re-ordered, as the elements which are to be removed, are temporarily overwritten by other elements which would fill the gap.

With an multiset, you can't override the value for a given iterator, as the iterator is a product of the defined sort function and the current content.

If this works with MSVC, then that STL implementation is doing more than the standard requires. Not safe to rely on that, as it isn't guaranteed.

Ext3h
  • 5,713
  • 17
  • 43