私はstd::set<int>
を頻繁に使用しており、そのようなセットに数字が含まれているかどうかを確認するだけです。
私は書くのが自然だと思うでしょう:
if (myset.contains(number))
...
しかし、contains
メンバーがないため、面倒なことを書く必要があります。
if (myset.find(number) != myset.end())
..
またはそれほど明白ではない:
if (myset.count(element) > 0)
..
この設計決定の理由はありますか?
おそらく、彼らがstd::set
とstd::multiset
を可能な限り似せようとしているからだと思います。 (そして明らかにcount
はstd::multiset
に対して完全に理にかなった意味を持ちます。)
個人的にはこれは間違いだと思います。
count
がcontains
のつづりが間違っていると見せかけ、テストを次のように記述しても、それほど悪くは見えません。
if (myset.count(element))
...
それでも残念です。
if (s.contains())
を記述できるようにするには、contains()
はbinary_search
のようにbool
(またはbool
に変換可能な型)を返す必要があります。
基本的理由設計決定の背後にあるnotこの方法でそれを行うには、bool
を返すcontains()
が要素の場所に関する貴重な情報を失うコレクションにあります。 find()
は、その情報を反復子の形式で保存して返すため、STLのような汎用ライブラリーの場合に適しています。彼がよく説明したように、これは常にアレックスステパノフの指針でした(たとえば here )。
一般的なcount()
アプローチについては、大丈夫な回避策であることが多いですが、問題はacontains()
する必要があります。
それは、bool contains()
が非常にいいものではなく、必要でさえないということではありません。しばらく前に、ISO C++標準-将来の提案グループでこのまったく同じ問題について 長い議論 がありました。
特定のケースを調査しており、大きな画像は表示されていません。 ドキュメントstd::set
で述べられているように、 AssociativeContainer コンセプトの要件を満たしています。このコンセプトでは、contains
メソッドを使用しても意味がありません。std::multiset
およびstd::multimap
にはほとんど役に立たないためですが、count
メソッドはすべて正常に機能します。メソッドcontains
は、std::set
、std::map
、およびそれらのハッシュバージョン(std::string
のsize()
のようなcount
など)のlength
のエイリアスとして追加できますが、ライブラリ作成者が追加したように見えますそれの本当の必要性を見ない。
std::set
にcontains
がなく、0
または1
のみを返すcount
がない理由はわかりませんが、テンプレート化されたcontains
ヘルパー関数を次のように記述できます。
template<class Container, class T>
auto contains(const Container& v, const T& x)
-> decltype(v.find(x) != v.end())
{
return v.find(x) != v.end();
}
そして、次のように使用します:
if (contains(myset, element)) ...
set
の本当の理由は私には謎ですが、map
のこの同じデザインの考えられる説明の1つは、人々が誤って非効率的なコードを書くことを防ぐためです。
if (myMap.contains("Meaning of universe"))
{
myMap["Meaning of universe"] = 42;
}
これは、2つのmap
ルックアップになります。
代わりに、イテレーターを取得する必要があります。これにより、イテレータを再利用する必要があるという精神的なヒントが得られます。
auto position = myMap.find("Meaning of universe");
if (position != myMap.cend())
{
position->second = 42;
}
map
ルックアップを1つだけ消費します。
set
とmap
が同じ肉から作られていることに気付いたら、set
にもこの原則を適用できます。つまり、set
に存在する場合にのみset
のアイテムを操作する場合、この設計により、次のようにコードを記述できなくなります。
struct Dog
{
std::string name;
void bark();
}
operator <(Dog left, Dog right)
{
return left.name < right.name;
}
std::set<Dog> dogs;
...
if (dogs.contain("Husky"))
{
dogs.find("Husky")->bark();
}
もちろん、これはすべて単なる推測にすぎません。
Binary_searchはどうですか?
set <int> set1;
set1.insert(10);
set1.insert(40);
set1.insert(30);
if(std::binary_search(set1.begin(),set1.end(),30))
bool found=true;