为什么使用像这样的find_if失败?

时间:2016-10-20 15:24:19

标签: c++ dictionary stl find stl-algorithm

我想从地图中找到第一个非零元素,因此我做了以下代码:

#include <map>
#include <iostream>
#include <algorithm>

bool nonzero(std::map<char,int>::const_iterator& it);

int main()  {
    std::map<char, int> m;
    m['a'] = 0;
    m['b'] = 1;
    std::map<char,int>::iterator it = std::find_if(m.begin(), m.end(), nonzero);
    std::cout << it->first << '\t' << it->second << std::endl;
    return 0;
}


bool nonzero(std::map<char,int>::const_iterator& it)    {
    return it->second;
}

g ++给出了非常复杂的错误,并说:

/usr/include/c++/5/bits/predefined_ops.h:234:30: error: invalid initialization of reference of type ‘std::_Rb_tree_const_iterator<std::pair<const char, int> >&’ from expression of type ‘std::pair<const char, int>’
  { return bool(_M_pred(*__it)); }

我不明白它的含义以及我的程序失败的原因。

3 个答案:

答案 0 :(得分:5)

nonzero调用的find_if函数的预期类型不是 std::map<char,int>::const_iterator&,而是const std::pair<const char, int> &

事实上,如果你查看一些online documentation for find_if,你会发现一元谓词的格式为:

bool UnaryPredicate(const Type&)

Type在您的案例std::pair<const char, int>中(对于一般std::map<Key, Value>,类型为std::pair<const Key, Value>)。

因此,您可以调整功能,将const&传递给std::pair

bool nonzero(const std::pair<const char, int> & p)
{
    return (p.second != 0);
}

请注意,使用带有lambdas的C ++ 14 auto会简化您的代码,例如:

auto it = std::find_if(m.begin(), m.end(), [](const auto& p){
    return (p.second != 0);
});

另请注意,该对的格式为std::pair<const Key, Value>(不仅仅是pair<Key, Value>非const键。)

答案 1 :(得分:4)

find_ifvalue_type(实际上是iterator.operator*())传递给传递给它的函数/函数对象。您的nonzero应该接受std::map<char,int>::value_type const&作为参数,或者更加简洁:std::pair<const char, int> const&

bool nonzero(std::pair<const char, int> const& element) {
    return it.second;
}

请注意,该对的密钥为const。如果你省略它,你将复制你检查的每个地图元素。

如果您可以使用C ++ 14或更高版本,您还可以使用auto和通用lambda来缩短它:

auto it = std::find_if(m.begin(), m.end(), [](auto const& pair){ return p.second; });

和C ++ 11版本:

auto it = std::find_if(m.begin(), m.end(), [](std::pair<const char, int> const& pair){ return p.second; })

答案 2 :(得分:2)

功能接受:

bool nonzero(const std::map<char,int>::value_type& value);

std::pair<const char,int>,而不是迭代器

在使用该迭代器之前,您应该通过与find_if进行比较来检查std::map::end()的结果。