I think the following reduced C++11 code should be valid.
unordered_map<string,string> test;
auto it = remove_if( test.begin(), test.end(),
[] (const decltype(test)::value_type &entry) { return true; } );
But it fails to compile with g++ 6.3, complaining about a deleted assignment operator of std::pair, but AFAIK that operator is not deleted.
/usr/include/c++/6/bits/stl_algo.h:868:16: error: use of deleted function ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=( ...
*__result = _GLIBCXX_MOVE(*__first);
Is this a compiler/glibc bug or is the code really invalid for some reason I fail to see?
Let's look at remove_if documentation:
The type of dereferenced ForwardIt must meet the requirements of MoveAssignable.
That is, “given t, a modifiable lvalue expression of type T and rv, an rvalue expression of type T, the expression t = rv must be valid and [behave as expected]”.
Here, you pass unordered_map<string, string>'s iterator to remove_if. Let's have a look. According to unordered_map documentation,
value_typeis defined asstd::pair<const Key, T>
So, std::pair<const string, string>.
Let's look at pair's operator=. Most notably:
template< class U1, class U2 > pair& operator=( const pair<U1,U2>& other );does not participate in overload resolution unlessstd::is_assignable_v<first_type&, const U1&>andstd::is_assignable_v<second_type&, const U2&>are both true.
Here, std::is_assignable_v<const string&, const string&> is not true, therefore the operator is not available. Therefore the pair is not MoveAssignable. Therefore remove_if cannot be used on those iterators.
So that would make your code invalid.
std::pair<const string, string> does have deleted assignment operator(s), because you can't change first.
The key_type of all the map-like containers in the STL are const, because otherwise you could break the lookup of elements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With