12

STL コンテナーでは、保存された値がコピー構築可能であり、割り当て可能である必要があります。const T は明らかに任意の T の割り当て可能な型ではありませんが、私はそれを使用しようとしましたが (好奇心が強いだけです)、それがコンパイルされ、さらに割り当て可能な型として動作することがわかりました。

vector<const int> v(1);
v[0] = 17;

これは Visual Studio 2008 で正常に実行され、v[0] が 17 に割り当てられます。

4

2 に答える 2

12

他の人が示唆しているように、これは実装のバグではありません。

C++ 標準ライブラリ機能の要件に違反しても、プログラムが不正な形式になるわけではなく、未定義の動作が発生します。

コンテナに格納された値の型はコピー構築可能で代入可能でなければならないという要件に違反したため (const型は明らかに代入可能ではありません)、プログラムは未定義の動作を示します。

C++ 標準の該当する言語は、C++03 17.4.3.6 [lib.res.on.functions] にあります。

特定のケース (置換関数、ハンドラー関数、標準ライブラリ テンプレート コンポーネントのインスタンス化に使用される型の操作) では、C++ 標準ライブラリは C++ プログラムによって提供されるコンポーネントに依存します。これらのコンポーネントが要件を満たさない場合、標準は実装に要件を課しません。

特に、次の場合の効果は定義されていません。

...

  • テンプレート コンポーネントをインスタンス化するときにテンプレート引数として使用される型の場合、その型の操作が該当する要件の節のセマンティクスを実装しない場合。

Visual C++ 標準ライブラリの実装では、const 修飾を暗黙のうちに削除または無視するなど、このコードで何でも行うことができますが、それでも標準に準拠しています。

于 2011-02-09T01:45:52.400 に答える
1

これはうまくいかないはずです。§23.1 ¶ 3 では、あなたが言ったように、コンテナーに格納されるオブジェクトはCopyConstructible(§20.1.3 で指定されているように) である必要があると指定されていますAssignable

型のAssignable要件は、型Ttありu、型Tである場合、次のことができることです。

t = u

T&as 戻り値を持ち、as 事後条件とt同等です。u(§23.1 ¶4)

したがって、const型は明らかにそうではありません。Assignableなぜなら、t = uそうするとコンパイル エラーが発生するからです (§7.1.5.1 ¶5)。

これはマイクロソフトの実装のバグだと思います。Linux 上の g++ は、a をインスタンス化しようとしても、典型的な 25 カジリオン行のテンプレート エラーを出力しますvector<const int>(念のため、フラグを使用した場合と使用しない場合の両方でテストされています-std=c++0x)。

ちなみに、こちらのIBM FAQでも詳しく説明されています。


理論的には、@James McNellis が言ったように、コンパイラーはベクターのインスタンス化を爆破する必要はありません (未定義の動作の場合、すべてが正常に機能することを含め、何かが起こる可能性があります)。ただし、割り当てステートメントには、コンパイル エラーが発生するはずの標準違反があります。

実際、メンバーは;operator[]を返します。(§23.1 ¶5 表 66)vector<const int>::referenceの左辺値である必要があること。は型なので、左辺値になりTます。したがって、(§7.1.5.1 ¶5) に行き着きます。これは、要素への代入を実行しようとするコードを「形式が正しくない」と定義しており、コンパイル エラーまたは少なくとも警告が必要です。は診断可能なルールです (§1.4 ¶1-2) (「診断不要」ステートメントは指定されていません)。 Tconstconstconstconst


最終編集

実際、@James McNellis は正しいです。をインスタンス化して未定義の動作を呼び出すと、通常のルールは値を持たなくなるため、要素タイプから を削除したり、通常の鼻の悪魔を生成したりvector<const int>するなど、実装は依然として標準に準拠しています。const

于 2011-02-09T01:21:52.247 に答える