STLアルゴリズムとconst_iterator
質問
今日、コンテナ内で一致するシンボルを見つけるための小さな述語を書きました。
しかし、私は問題に直面しています:この述語をクラスのconstメソッド内のstd::find_if
呼び出しで使用して、このクラスのメンバーであるコンテナを検索したいです。
しかし、std::find
もconst_iterators
も<=>!
一部のC ++参照を確認しましたが、<=>を受け入れる/返す<=>または<=>のバージョンがないようです。私が見たものから、これらのアルゴリズムがイテレータによって参照されるオブジェクトを変更する方法がないので、私はちょうど理由を理解できません。
SGI実装で<=>に文書化する方法は次のとおりです。
最初のイテレータiを返します * i ==となる範囲[first、last) 値。そのようなものがない場合、最後を返します イテレータが存在します。
解決
std::find
およびstd::find_if
は、特定のコンテナの*::const_iterator
で確実に操作できます。これらの関数のシグネチャを偶然見て、誤解していますか?
template <class InputIterator, class Type>
InputIterator find(InputIterator first, InputIterator last, const Type& val);
ここでInputIterator
はテンプレート型パラメーターの名前であり、const_iterator
はその要件を満たしていることに注意してください。
または、おそらく、const
(つまりconst値を参照するイテレータ)と<=>イテレータ(つまり、それ自体が<=>であるイテレータ)を混同していますか?
他のヒント
std::find
とstd::find_if
はどちらもイテレータタイプをテンプレートパラメータとして使用するため、 はconst_iterators
で操作できます。簡単な例:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> x;
std::fill_n(std::back_inserter(x), 20, 2);
x.push_back(3);
std::vector<int>::const_iterator b = x.begin();
std::vector<int>::const_iterator e = x.end();
std::vector<int>::const_iterator p = std::find(b, e, 3);
std::cout << *p << " found at position: " << std::distance(b, p) << "\n";
return 0;
}
これは、適切に機能するC ++コンパイラで受け入れられ、次のような結果を生成する必要があります。
3が位置20で見つかりました
同じ問題が発生しました。メンバーベクトルでfind_if
を呼び出しているメンバー関数があり、メンバー関数const
を作成しようとしたときにコンパイラーからエラーが返されました。これは、iterator
ではなくconst_iterator
に<=>の戻り値を割り当てていたためであることが判明しました。これにより、コンパイラは、<=>のパラメーターも<=>ではなく<=>でなければならないことを想定しました。これは、<=>メンバーベクトルから取得できませんでした。
万が一あなたが私と同じ理由でここにいる場合:
error: no matching function for call to ‘find(std::vector<int>::const_iterator, std::vector<int>::const_iterator, int)’
const_iterator
とは関係ありません。おそらく#include <algorithm>
を忘れただけです:-)
このコードで問題が発生しました:
std::string str;
std::string::const_iterator start = str.begin();
std::string::const_iterator match = std::find(start, str.end(), 'x');
エラーは<!> quot; std :: find <!> quot;に一致するオーバーロードがありませんでした。
必要な修正は、cend()を使用することでした。 cbegin()が必須ではないのはわかりにくいです。なぜ変換が(暗黙的に)大丈夫で、関数パラメータとしてのend()がそうでないのかはわかりません。