この拡張の動機は、適合プログラムによって検出可能であり、したがって適合していないため、参照(constおよびその他)に関して、vector<bool>
より振る舞うようvector<char>
にすることです。
前書き
1998年以来、vector<bool>
「あまりコンテナではない」と非難されてきました。 LWGの最初の問題の1つであるLWG 96が議論を始めました。17年後の今日、vector<bool>
ほとんど変わっていません。
このホワイトペーパーでは、の動作がのvector<bool>
他のすべてのインスタンス化とどのように異なり、vector
汎用コードに悪影響を与えるかについて、いくつかの具体的な例を取り上げます。ただし、同じペーパーでvector<bool>
は、適切に実装された場合に非常に優れたパフォーマンスプロパティが持つ可能性があることについて詳細に説明しています。
概要: vector<bool>
悪いコンテナではありません。実際にはかなり便利です。それは単に悪い名前を持っています。
戻る const_reference
上記で紹介し、ここで詳しく説明しvector<bool>
ているように、一般的なコードでは、他のvector
インスタンス化とは動作が異なるのが悪い点です。具体的な例を次に示します。
#include <cassert>
#include <vector>
template <class T>
void
test(std::vector<T>& v)
{
using const_ref = typename std::vector<T>::const_reference;
const std::vector<T>& cv = v;
const_ref cr = cv[0];
assert(cr == cv[0]);
v[0] = 1;
assert(true == cv[0]);
assert(cr == cv[0]); // Fires!
}
int
main()
{
std::vector<char> vc(1);
test(vc);
std::vector<bool> vb(1);
test(vb);
}
標準仕様では、マーク// Fires!
されたアサートがトリガーされるが、がtest
で実行された場合に限られvector<bool>
ます。で実行したときvector<char>
(または任意vector
のほかbool
の適切なデフォルト以外のときにT
割り当てられている)、テストが通過します。
libc ++の実装ではvector<bool>
、汎用コードでの動作が異なることによる悪影響を最小限に抑えようとしました。これを実現するために行ったことの1つは、指定されたと同じようにproxy-referenceを作成 vector<T>::const_reference
することですが、それを介して割り当てることはできません。つまり、libc ++では、ビットのコピーではなく、本質的に内のビットへのポインタです。vector<T>::reference
vector<T>::const_reference
vector
上記++のlibcにはtest
両方のためのパスvector<char>
とvector<bool>
。
どんな費用で?
欠点は、質問に示されているように、この拡張機能が検出可能であることです。ただし、実際にはこのエイリアスの正確なタイプを考慮しているプログラムはほとんどなく、より多くのプログラムが動作を考慮しています。
この不適合の動機は何ですか?
汎用コードでのlibc ++クライアントの動作を改善するには、おそらく十分なフィールドテストの後に、C ++業界全体を改善するために、この拡張機能を将来のC ++標準に提案します。
そのような提案はbit_vector
、今日のvector<bool>
ものとほとんど同じAPIを持っているが、const_reference
ここで説明されているようないくつかのアップグレードを伴う新しいコンテナ(たとえば)の形で来るかもしれません。その後、スペシャライゼーションの廃止(および最終的な削除)が行われvector<bool>
ます。 bitset
この部門では、add const_reference
やイテレータのセットなどの小さなアップグレードも使用できます。
つまり、後bitset
から見るとvector<bool>
(これは名前を変更する必要がありますbit_vector
-または何か)、そのままarray
ですvector
。そして、アナロジーは、私たちが話しているか否かが当てはまるべきbool
とvalue_type
のvector
とarray
。
libc ++の拡張機能として開始されたC ++ 11およびC ++ 14機能の例が複数あります。これが標準の進化の仕方です。実際に実証され 、正フィールドでの経験は、強力な影響力を運びます。既存の仕様を(あるべきように)変更することに関しては、標準の人々は保守的な束です。推測は、正しく推測していると確信している場合でも、国際的に認められた標準を進化させるためのリスクの高い戦略です。
vector<bool>
し、より一流の基盤を築くことができるでしょうか?