Unordered_set :: remove_if (): C3892: cannot assign const variable

I have code like:

unordered_set<AttrValue> output; ... auto requiredType = variables.at(arg.value); auto end = remove_if(output.begin(), output.end(), [&](AttrValue x) { return !matchingOutputType(requiredType, ast->getNodeType(ast->getNodeKeyAttribute(x))); }); // queryevaluator_getcandidatelist.cpp(179) output.erase(end); 

Error in line 4 of the code. So I think this is due to remove_if . But what is wrong? Is the output not defined constant?


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

Output Window:

 3>c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(1840): error C3892: '_Next' : you cannot assign to a variable that is const 3> c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(1853) : see reference to function template instantiation '_FwdIt std::_Remove_if<std::_List_unchecked_const_iterator<_Mylist>,_Pr>(_FwdIt,_FwdIt,_Pr)' being compiled 3> with 3> [ 3> _FwdIt=std::_List_unchecked_const_iterator<std::_List_val<int,std::allocator<AttrValue>>>, 3> _Mylist=std::_List_val<int,std::allocator<AttrValue>>, 3> _Pr=`anonymous-namespace'::<lambda4> 3> ] 3> h:\dropbox\sch\cs3202\code\source\query\query evaluator\queryevaluator_getcandidatelist.cpp(179) : see reference to function template instantiation '_FwdIt std::remove_if<std::_List_const_iterator<_Mylist>,`anonymous-namespace'::<lambda4>>(_FwdIt,_FwdIt,_Pr)' being compiled 3> with 3> [ 3> _FwdIt=std::_List_const_iterator<std::_List_val<int,std::allocator<AttrValue>>>, 3> _Mylist=std::_List_val<int,std::allocator<AttrValue>>, 3> _Pr=`anonymous-namespace'::<lambda4> 3> ] 
+4
source share
2 answers

In accordance with the standard Β§ 23.2.4.6

For associative containers, where the value type matches the type of key type, the iterator and const_iterator are constant iterators.

So you can’t even do

 std::unordered_set<int> s{1, 2, 3, 4}; *s.begin() = 42; 

And, of course, you cannot use the std::remove_if(ForwardIt first, ForwardIt last, ...) function to remove elements from std::set and std::unordered_set :

The type of dereferenced ForwardIt must meet the requirements of MoveAssignable.

+5
source

The std::remove_if ( not the member function unordered_set::remove_if , which is mentioned in the name but does not exist) does not actually delete anything; he reorders the sequence by overwriting the elements that match the criteria passed with later elements in the sequence. Therefore, this requires a sequence of mutable objects. The objects in the sequence controlled by unordered_set are not changed, since changing them can disrupt the order that the container imposes.

To remove an item with a given key, use unordered_set::erase .

To remove an element or elements that meet a more general criterion, you need to cast: std::find_if over the container in order to match ( std::find_if will do this) and delete the elements as they are found using unordered_set::erase . Be careful: after you delete an element, the iterator that points to it no longer works, so your code should save the iterator that points to the next element in the sequence. There are many examples of how to do this.

0
source

All Articles