【问题标题】:unordered_set::remove_if(): C3892: cannot assign to a variable that is constunordered_set::remove_if(): C3892: 无法分配给 const 变量
【发布时间】:2013-03-20 22:43:19
【问题描述】:

我有这样的代码:

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);

错误出现在代码的第 4 行。所以我认为是因为remove_if。但是怎么了?输出未定义常量?


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

输出窗口:

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>          ]

【问题讨论】:

标签: c++


【解决方案1】:

根据标准 § 23.2.4.6

对于值类型与 key 类型,iterator 和 const_iterator 都是常量迭代器。

所以,你甚至不能这样做

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

当然,您不能使用std::remove_if(ForwardIt first, ForwardIt last, ...) 函数从std::setstd::unordered_set 中删除元素:

解引用的ForwardIt的类型必须满足MoveAssignable的要求。

【讨论】:

  • 那我该怎么办?我在这里使用 set 是因为本质上,我只想存储唯一值。如果我使用向量,我需要检查该值是否存在然后插入。直接的方法是将集合转换为向量,然后从那里开始工作。听起来效率低下?我该如何解决这个问题?
  • @JiewMeng,请参阅我对您问题的评论中的link
【解决方案2】:

算法std::remove_if不是成员函数unordered_set::remove_if,在标题中提到但不存在)实际上并没有删除任何东西;它通过用序列中后面的元素覆盖与传入标准匹配的元素来重新排序序列。所以它需要一系列可变对象。由unordered_set 管理的序列中的对象是不可变的,因为修改它们可能会破坏容器施加的顺序。

要删除具有给定键的元素,请使用unordered_set::erase

要删除一个或多个符合更一般标准的元素,您必须自己动手:遍历容器寻找匹配项(std::find_if 会这样做),并在找到元素时使用 @ 删除它们987654326@。注意:在你删除一个元素后,指向它的迭代器不再有效,所以你的代码必须保存一个指向序列中下一个元素的迭代器。有很多关于如何做到这一点的例子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多