2016-10-25 58 views
4

我有一个简单的程序,调用std::find_if,我想我已经通过了前两个参数作为迭代器,第三个作为预测,但代码仍然不会编译,任何想法?为什么find_if不能在我的程序中工作?

#include <string> 
#include <cctype> 
#include <algorithm> 

bool notspace(char ch); 
bool space(char ch); 

int main() { 
    typedef std::string::const_iterator iter; 
    iter i; 
    std::string s = "ab c"; 
    i = std::find_if(i, s.end(),space); 
    return 0; 
} 

bool space(char ch) { 
    return std::isspace(ch); 
} 

错误消息:

q-isspace.cpp: In function ‘int main()’: 
q-isspace.cpp:12:38: error: no matching function for call to ‘find_if(iter&, std::__cxx11::basic_string<char>::iterator, bool (&)(char))’ 
    i = std::find_if(i, s.end(),space); 
            ^
In file included from /usr/include/c++/5/algorithm:62:0, 
       from q-isspace.cpp:3: 
/usr/include/c++/5/bits/stl_algo.h:3806:5: note: candidate: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate) 
    find_if(_InputIterator __first, _InputIterator __last, 
    ^
/usr/include/c++/5/bits/stl_algo.h:3806:5: note: template argument deduction/substitution failed: 
q-isspace.cpp:12:38: note: deduced conflicting types for parameter ‘_IIter’ (‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >’ and ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’) 
    i = std::find_if(i, s.end(),space); 
+3

'i'和'j'没有被初始化为任何东西。那么'find_if'应该从哪里开始呢? – UnholySheep

回答

8

您将i的类型std::string::const_iterator(也未初始化)作为std::find_if的第一个参数。然后你通过s.end()返回std::string::iterator。这两个迭代器有不同的类型,而std::find_if期望它们是相同的类型。

拇指正确的规则,是将呼叫配对begin()end()

#include <string> 
#include <cctype> 
#include <algorithm> 

bool notspace(char ch); 
bool space(char ch); 

int main() { 
    typedef std::string::const_iterator iter; 
    iter i,j; 
    std::string s = "ab c"; 
    i = std::find_if(s.begin(), s.end(),notspace); 
    j = std::find_if(s.begin(), s.end(),space); 
    return 0; 
} 

bool space(char ch) { 
    return std::isspace(ch); 
} 

bool notspace(char ch) { 
    return !std::isspace(ch); 
} 
+0

如果一个是'const_iterator'而另一个是'iterator',那么问题会是重要的吗? – buzhidao

+0

@buzhidao,是的。模板函数类型演绎非常具体。 'std :: find_if'只能命名一个'InputIterator'类型 – StoryTeller

+0

我发现当我在'std :: string'之前使用'const'时,也没有编译错误。 – buzhidao

5
int main() { 
    typedef std::string::const_iterator iter; 
    iter i,j; 
    std::string s = "ab c"; 
    i = std::find_if(i, s.end(),notspace); 
    j = std::find_if(i, s.end(),space); 
    return 0; 
} 

你不initalising你i变量,所以它不指向任何东西。这意味着[i, s.end())不构成有效范围,因此您拨打find_if()将无法​​正常工作。

试试这个:

i = std::find_if(s.begin(), s.end(), notspace); 
+0

这不会产生编译器错误。 – juanchopanza

+0

@juanchopanza const_iterator for'i','iterator' for's.end()',扣除失败? –

+0

是的,就是这样。 – juanchopanza

3
iter i,j; 
std::string s = "ab c"; 
i = std::find_if(i, s.end(),notspace); 

这与默认初始化迭代器作为第一个参数调用std::find_if。该迭代器与s中的任何迭代器都没有关系,所以结果将是无稽之谈。将呼叫更改为

`std::find_if(s.begin(), s.end(), notspace); 

并在另一个呼叫中做类似的更改。

+1

我很确定编译器错误是由于具有不同类型的迭代器造成的。 – juanchopanza

+1

@juanchopanza - yup,可能还需要将typedef更改为'typedef std :: string :: iterator iter;'以便返回类型匹配。 –

3

如果你想知道为什么你的编译错误,那是因为std::find_if只有1个模板参数。 s.end()是一个正常的迭代器,而iconst_iterator,那些不匹配。然后有i未初始化的问题,这会导致运行时错误。只需使用s.begin()

i = std::find_if(s.begin(), s.end(),space); 

如果你希望能够通过i改变内容,你应该让一个正常的迭代器:

typedef std::string::iterator iter; 
1

i变量未初始化。更优雅的代码方式是使用lambda函数,如下所示。

#include <string> 
    #include <cctype> 
    #include <algorithm> 

    int main() { 
     typedef std::string::const_iterator iter; 
     iter i,j; 
     std::string s = "ab c"; 
     i = std::find_if(s.begin(), s.end(),[](char ch) { return std::isspace(ch); }); 
     j = std::find_if(s.begin(), s.end(),[](char ch) { return !std::isspace(ch); }); 
     return 0; 
    } 
相关问题