セクション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 ++の最初の導入以来一貫してこの仕様に従っていないことに注意してください。
この不適合の動機は何ですか?
この拡張の動機は、適合プログラムによって検出可能であり、したがって不適合であるため、vector<bool>
を参照(constなど)に関してvector<char>
のように動作させることです。
はじめに
1998年以降、vector<bool>
は「コンテナではない」と非難されてきました。 LWG 96 、最初のLWG問題の1つが議論を開始しました。今日、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つは、指定されたvector<T>::const_reference
と同様に、vector<T>::reference
をproxy-referenceにすることです。ただし、それ。つまり、libc ++では、vector<T>::const_reference
は基本的に、そのビットのコピーではなく、vector
内のビットへのポインターです。
Libc ++では、上記のtest
はvector<char>
とvector<bool>
の両方に渡されます。
費用は?
欠点は、質問に示されているように、この拡張機能が検出可能であることです。ただし、実際にはこのエイリアスの正確なタイプを気にするプログラムはほとんどなく、動作を気にするプログラムも増えています。
この不適合の動機は何ですか?
Libc ++クライアントの汎用コードでの動作を改善するために、おそらく十分なフィールドテストの後、C++業界全体の改善のために、この拡張機能を将来のC++標準に提案してください。
このような提案は、現在のbit_vector
とほぼ同じAPIを備えた新しいコンテナ(たとえばvector<bool>
)の形で提供されますが、ここで説明するconst_reference
などのいくつかのアップグレードがあります。 vector<bool>
スペシャライゼーションの廃止(および最終的な削除)が続きます。 bitset
は、この部門で少しアップグレードすることもできます。 const_reference
とイテレータのセットを追加します。
つまり、bitset
がarray
であるように、後知恵ではvector
がvector<bool>
になります(bit_vector
に変更する必要があります)。そして、bool
とvector
のvalue_type
としてarray
について話しているかどうかにかかわらず、類推は真実である必要があります。
Libc ++の拡張機能として開始されたC++ 11およびC++ 14機能の例は複数あります。これが標準の進化です。実際の実証済み肯定的現場経験は強い影響を及ぼします。標準の人々は、既存の仕様を変更することになると、保守的な束になります(そうあるべきです)。推測は、正しく推測していると確信している場合でも、国際的に認められた標準を進化させるためのリスクの高い戦略です。