[解決済み] libc++ の vector<bool>::const_reference はなぜ bool ではないのですか?
質問
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++ が最初に導入されて以来、一貫してこの仕様に従わないことに注目します。
この非適合性の動機は何でしょうか。
どのように解決するのですか?
この拡張は、適合するプログラムによって検出可能であるため、不適合とする動機は
vector<bool>
のような振る舞いをすることです。
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>
が一般的なコードで異なる振る舞いをすることの弊害を最小限にしようとしました。 これを達成するために行ったことのひとつが
vector<T>::const_reference
a
プロキシリファレンス
と同じように、指定された
vector<T>::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
は
vector<bool>
(にリネームされるべきです)。
bit_vector
-- などに変更する必要があります。
array
は
vector
. について話しているかどうかに関わらず、この類推は成り立つはずです。
bool
を
value_type
の
vector
と
array
.
C++11 や C++14 の機能が libc++ の拡張機能としてスタートした例は複数あります。 このように標準は進化していくのです。 実際の が実証した ポジティブ 現場での経験は強い影響力を持ちます。 既存の仕様を変更することに関しては、標準の専門家は保守的な集団です (そうあるべきです)。 推測は、たとえ自分が正しく推測していると確信している場合でも、国際的に認められた標準を進化させるためには危険な戦略です。
関連
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] C++で仮想関数が必要な理由とは?
-
[解決済み] std::vector にある項目が存在するかどうかを調べるには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる