2011-02-09 10 views
11

STLコンテナは、格納された値をコピーコンストラクタブルおよびアサイナブルにする必要があります。 const Tは明らかにどのTでも代入可能な型ではありませんが、私はそれを使用しようとしました(ちょうど興味があります)、それがコンパイルされ、さらに代入可能な型として動作することがわかりました。VC++では、STLコンテナにconst型を使用できます。どうして?

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

は、この成功したのVisual Studio 2008で実行され、これは、単に動作しないはずV [0]

+1

VS - 2010では、v [0] 'に新しい値*を割り当てることができます。それを試してみてください! –

+1

私はVCがtypeid(ベクトル :: value_type).name()について何を提供しているのか不思議です(そしてtypeid(ベクトル :: value_type).name()またはdemangleと比較してください)。 –

+0

一つと同じ: 'int'。 –

答えて

1

17に割り当てられます。 §23.1¶3では、あなたが言ったように、コンテナに格納されたオブジェクトはCopyConstructible(§20.1.3で指定)とAssignableである必要があります。タイプTため

Assignable要件はtとタイプTuされ、あなたがすることができる、ということです。

t = u 

持つ戻り値としてT&と事後条件としてuに相当tt = uを行うことは、コンパイル・エラー(§7.1.5.1¶5)を引き上げるため、(§23.1¶4)

はこのように、constタイプは、はっきりAssignableではありません。

これはMicrosoft実装のバグだと思います。 Linuxのg ++​​は、vector<const int>-std=c++0xフラグの有無にかかわらずテスト済み)をインスタンス化しようとしても、典型的な25kajillion行のテンプレートエラーを出力します。なお、これについては、IBM FAQでも詳細に説明する。別ウィンドウ(タブ)の大きな表示で見る理論的には


、@James McNellisは(それは未定義の動作だ場合何が起こることができます - すべての作業罰金を含む)コンパイラがベクトルのインスタンス化に爆破するために必要とされていない、言ったように。ただし、割り当てステートメントには、コンパイルエラーを生成する標準違反があります。

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


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

+1

容易それを動作可能にする方法は、remove_const型の特性です(この正確な特性は、0xでなければならないかもしれませんが、おそらく別の名前であるべきです)。 –

+0

@Fred Nurk:あなたが言ったようなものでしょう。実際には、私が書いた 'mutable'はbrainfartだと思います。' constable'メソッドで 'mutable'をnon-'const'(§7.1.2¶8)のクラスフィールドに入れて変更できるようにしています。テンプレート型から 'const'を削除することとは何の関係もありません。 –

+0

これは実装上のバグではありません。 OPのプログラムは未定義の動作を示します。 –

12

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

C++標準ライブラリ機能の要件に違反しても、プログラムが不正な形にならないため、未定義の動作が発生します。

コンテナに格納されている値の型がコピー可能であり、かつ割り当て可能でなければならないという要件に違反しています(const型は、明らかに割り当てられません)。

C++標準から該当する言語に見出すことができるC++ 03 17.4.3.6 [lib.res.on.functions]:特定の場合(置換関数、ハンドラ関数、上の操作で

標準ライブラリテンプレートコンポーネントをインスタンス化するのに使用される型)、C++標準ライブラリはC++プログラムによって提供されるコンポーネントに依存します。これらのコンポーネントが要件を満たしていない場合、この標準は実装上の要件を置かない。

特に

、効果は次の場合に定義されていない:

...テンプレート・コンポーネントのインスタンスを作成する際にテンプレート引数として使用されるタイプのため

  • 、タイプの操作は実装していない場合該当する要件の節のセマンティクス。

のVisual C++標準ライブラリの実装は黙っのconst修飾を取り除くか、無視を含め、このコードで何かを行うことができ、そしてそれはまだ標準規格に準拠しています。

+3

私の意見のほんのわずかなところで、ここでサイレントな資格の削除は本当に、本当に醜いです。 –

+0

資格の削除は、実際には矛盾しますが、依然として標準に準拠したコードを破る可能性があります。't = u'の後に' t == u'を保証するconst修飾されたコピー代入演算子を持つクラスを書くことができます。そして、その後置条件を保証しない非const修飾コピー代入演算子です。このようにして、 'const T'は割り当て可能ですが、' T'は割り当てられません。私はこれに対して有効なユースケースを想像することはできません。もし私がそういうコードを見たら、私はおそらく泣くでしょう。 –

+0

標準では "assignable"が定義されているので、post-conditionはtとuが等価であると考えられます。 - BTW、C++ 0xは割り当て可能性要件を削除する予定ですか?私はもうドラフトの中でそれを見ることはできません。割り当てを必要としない操作がうまくいくことは意味があります。 – UncleBens

関連する問題