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_type
is 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