Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ compiler error on deleted assignment operator of pair<string,string>

Tags:

c++11

stl

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?

like image 813
Zólyomi István Avatar asked Sep 26 '17 08:09

Zólyomi István


2 Answers

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 as std::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 unless std::is_assignable_v<first_type&, const U1&> and std::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.

like image 112
spectras Avatar answered Oct 03 '22 03:10

spectras


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.

like image 34
Caleth Avatar answered Oct 03 '22 03:10

Caleth