93

セクション 23.3.7 クラスvector<bool>[vector.bool]、パラグラフ 1 には次のように記載されています。

template <class Allocator> class vector<bool, Allocator> {
public:
    // types:
    typedef bool              const_reference;
    ...

ただし、libc++ を使用すると、このプログラムはコンパイルに失敗します。

#include <vector>
#include <type_traits>

int
main()
{
    static_assert(std::is_same<std::vector<bool>::const_reference, bool>{}, "?");
}

さらに、C++ 標準は、C++98 までさかのぼってこの仕様で一貫していることに注意してください。さらに、libc++ が最初に導入されて以来、libc++ は一貫してこの仕様に従っていないことに注意してください。

この不適合の動機は何ですか?

4

1 に答える 1

101

適合するプログラムによって検出可能であり、従って不適合であるこの拡張の動機は、参照 (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>. a vector<char>(または適切な非デフォルトが割り当てられている場合はそれvector以外) で実行すると、テストに合格します。boolT

vector<bool>libc++ の実装では、一般的なコードで異なる動作をすることによる悪影響を最小限に抑えようとしました。これを達成するために行ったことの 1 つは 、指定された と同じようにproxy-referencevector<T>::const_referenceを作成することですが、それを介して代入することはできません。つまり、libc++ では、本質的には、そのビットのコピーではなく、内のビットへのポインターです。vector<T>::referencevector<T>::const_referencevector

libc++ では、上記は と の両方にtest渡されます。vector<char>vector<bool>

どのくらいの費用で?

欠点は、質問に示されているように、この拡張子が検出可能であることです。ただし、このエイリアスの正確なタイプを実際に気にするプログラムはほとんどなく、より多くのプログラムが動作を気にします。

この不適合の動機は何ですか?

ジェネリック コードで libc++ クライアントの動作を改善するには、十分なフィールド テストを行った後、C++ 業界全体の改善のために、この拡張機能を将来の C++ 標準に提案します。

このような提案は、bit_vector現在の とほぼ同じ API を持つ新しいコンテナ (例: )の形で提供される可能性がありますが、ここvector<bool>で説明するようないくつかのアップグレードが含まれていconst_referenceます。vector<bool>専門 化の非推奨 (および最終的な削除) が続きます。addや一連のイテレータなど、bitsetこの部門で少しアップグレードすることもできます。const_reference

つまり、後から考えるとbitsetto は to (名前を-- などvector<bool>に変更する必要があります) であり、そのままtoです。そして、とについて話しているかどうかにかかわらず、類推は当てはまるはずです。bit_vectorarrayvectorboolvalue_typevectorarray

libc++ の拡張機能として開始された C++11 および C++14 機能の例が複数あります。これが、標準が進化する方法です。実際に実証された 積極的な現場経験は、強い影響力を持っています。標準化を支持する人々は、既存の仕様の変更に関しては保守的です (そうあるべきです)。推測が正しいと確信している場合でも、推測することは、国際的に認められた標準を発展させるための危険な戦略です。

于 2015-08-12T19:55:07.263 に答える