2016-10-25 6 views
4

私はstd::find_ifを呼び出す単純なプログラムを持っていますが、最初の2つの引数をイテレータとして渡して、3番目を予測として渡すと思いますが、コードはまだコンパイルされません。私のプログラムで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

の最初のパラメータとしてstd::string::const_iterator(かつ初期化されていない)タイプのiを渡します。次に、を返します。std::string::iteratorが返されます。 2つのイテレーターは異なるタイプのものですが、std::find_ifはそれらが同じタイプであると予想しています。あなたはなぜあなたのコンパイルエラーを知りたい場合は

親指の正しいルールは、std::find_ifは1つのだけのテンプレートパラメータを持っているからだと、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'はただ1つの' 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; 
} 

あなたのi変数をinitalisingていないので、それは何を指していません。つまり、[i, s.end())は有効な範囲を構成しないため、find_if()への呼び出しは正しく機能しません。

代わりにこれを試してみてください:

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

コンパイラエラーは発生しません。 – juanchopanza

+0

@juanchopanza 'i 'の' const_iterator'、 's.end()'の 'iterator'、控除の失敗? –

+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

に電話をペアリングすることです。 s.end()は通常のイテレータであり、iconst_iteratorであり、一致しません。そして、iが初期化されていないという問題があり、実行時エラーが発生します。ただ、s.begin()を使用します。

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

あなたはiを通じて内容を変更することができるようにしたい場合は、あなたがそれを通常のイテレータにする必要があります。

typedef std::string::iterator iter; 
1

i変数が初期化されていません。コードのよりエレガントな方法は、下記のようにラムダ関数を使うことです。

#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; 
    } 
関連する問題