对<string,string>的删除赋值运算符的g++编译器错误

Zól*_*ván 5 stl c++11

我认为以下简化的 C++11 代码应该是有效的。

unordered_map<string,string> test;
auto it = remove_if( test.begin(), test.end(),
    [] (const decltype(test)::value_type &entry) { return true; } );
Run Code Online (Sandbox Code Playgroud)

但它无法使用 g++ 6.3 编译,抱怨 std::pair 的赋值运算符已删除,但 AFAIK 未删除该运算符。

/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);
Run Code Online (Sandbox Code Playgroud)

这是编译器/glibc 错误还是由于某些原因我看不到代码真的无效?

spe*_*ras 6

让我们看看remove_if文档:

该型反引用ForwardIt必须满足的要求MoveAssignable

也就是说,“给定t一个类型为Tand的可修改左值表达式rv,一个类型为 的右值表达式T,该表达式t = rv必须有效并且[行为如预期]”。

在这里,您将unordered_map<string, string>的迭代器传递给remove_if。我们来看一下。根据unordered_map文件

value_type 被定义为 std::pair<const Key, T>

所以,std::pair<const string, string>

让我们看看对的operator=. 最为显着地:

template< class U1, class U2 > pair& operator=( const pair<U1,U2>& other );不参与重载决议,除非std::is_assignable_v<first_type&, const U1&>std::is_assignable_v<second_type&, const U2&>两者都为真。

在这里,std::is_assignable_v<const string&, const string&>不是真的,因此运营商不可用。因此,该对不是 MoveAssignable。因此remove_if不能用于那些迭代器。

所以这会使您的代码无效。


Cal*_*eth 4

std::pair<const string, string> 确实已删除赋值运算符,因为您无法更改first.

STL 中所有key_type类似地图的容器的 都是 const,因为否则可能会破坏元素的查找。