简体   繁体   English

std :: remove_if中的const参数

[英]const arguments in std::remove_if

I'm going to remove elements from a list of pairs . 我要从对列表中删除元素。 When I'm using a pair like 当我使用一对像

std::pair<const int, bool>

I get the following compilation error: 我收到以下编译错误:

In file included from /usr/local/include/c++/6.1.0/utility:70:0, 在/usr/local/include/c++/6.1.0/utility:70:0中包含的文件中,

from /usr/local/include/c++/6.1.0/algorithm:60, 来自/usr/local/include/c++/6.1.0/algorithm:60,

from main.cpp:1: 来自main.cpp:1:

/usr/local/include/c++/6.1.0/bits/stl_pair.h: In instantiation of 'std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const int; /usr/local/include/c++/6.1.0/bits/stl_pair.h:在'std :: pair <_T1,_T2>&std :: pair <_T1,_T2> :: operator =(std ::)的实例化中pair <_T1,_T2> &&)[with _T1 = const int; _T2 = bool]': _T2 = bool]':

/usr/local/include/c++/6.1.0/bits/stl_algo.h:868:16: required from '_ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = std::_List_iterator > _Predicate = __gnu_cxx::__ops::_Iter_pred&)> >]' /usr/local/include/c++/6.1.0/bits/stl_algo.h:868:16:需要'_ForwardIterator std :: __ remove_if(_ForwardIterator,_ForwardIterator,_Predicate)[with _ForwardIterator = std :: _ List_iterator> _Predicate = __gnu_cxx :: __ ops :: _ Iter_pred&)>>]''

/usr/local/include/c++/6.1.0/bits/stl_algo.h:936:30: required from '_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::_List_iterator > _Predicate = main()::&)>]' /usr/local/include/c++/6.1.0/bits/stl_algo.h:936:30:需要'_FIter std :: remove_if(_FIter,_FIter,_Predicate)[与_FIter = std :: _ List_iterator> _Predicate = main ()::&)>]”

main.cpp:17:32: required from here main.cpp:17:32:从这里要求

/usr/local/include/c++/6.1.0/bits/stl_pair.h:319:8: error: assignment of read-only member 'std::pair::first' /usr/local/include/c++/6.1.0/bits/stl_pair.h:319:8:错误:只读成员'std :: pair :: first'的分配

first = std::forward(__p.first); first = std :: forward(__ p.first);

This is the sample code: 这是示例代码:

int main()
{
    int id = 2;

    std::list< std::pair <const int, bool> >  l;
    l.push_back(std::make_pair(3,true));
    l.push_back(std::make_pair(2,false));
    l.push_back(std::make_pair(1,true));

    l.erase(std::remove_if(l.begin(), l.end(), 
        [id](std::pair<const int, bool>& e) -> bool {
        return e.first == id; }));

    for (auto i: l) {
        std::cout << i.first << " " << i.second << std::endl;
    }
}

I know that (please correct me If I am wrong): 我知道(如果我错了,请纠正我):

  1. I will have exactly the same problem as long as there is constness in any element of the list, for example, a list <const int> will also return a compilation error. 只要列表的任何元素中存在list <const int> ,我就会遇到完全相同的问题,例如, list <const int>也会返回编译错误。

  2. If I remove the const in the first element of the pair the code will work. 如果我删除对中第一个元素中的const,代码将起作用。

  3. The more elegant and efficient way to do it is by using the remove_if list method, like this: 更优雅和有效的方法是使用remove_if list方法,如下所示:

     l.remove_if([id](std::pair<const int, bool>& e) -> bool { return e.first == id; }); 

but my question is, what are exactly the inner workings of std::remove_if that impose the elements of the container not being const ? 但我的问题是,std :: remove_if的内部工作原理是什么,它强加了容器的元素不是const

The general std::remove_if shuffles item values around to put the logically erased values at the end of the sequence (it's typically used in combination with member function erase to actually remove the logically erased values). 一般std::remove_if将项值改为std::remove_if ,将逻辑擦除的值放在序列的末尾(它通常与成员函数erase结合使用,以实际删除逻辑上擦除的值)。 It can't do that shuffling when an item isn't copyable or movable. 当物品不可复制或移动时,它不能进行洗牌。 Instead use std::list::remove_if . 而是使用std::list::remove_if

If you look at the type and iterator requirements of std::remove_if , you can see that the implementation must be similar to the following (from the link above): 如果查看std::remove_if的类型和迭代器要求,可以看到实现必须类似于以下内容(来自上面的链接):

template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
    first = std::find_if(first, last, p);
    if (first != last)
        for(ForwardIt i = first; ++i != last; )
            if (!p(*i))
                *first++ = std::move(*i);
    return first;
}

Ie, the algorithm assumes only that the iterators have forward capabilities, and elements are moveable, and it move s elements around. 即,该算法仅假设迭代器具有前向能力,并且元素是可移动的,并且它move s元素。 Of course, move s can't be done on const objects. 当然,不能在const对象上执行move s。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM