C ++ 11はvector <const T>を許可しますか?


82

コンテナの要件がC ++ 03からC ++ 11に変更されました。C ++ 03には包括的な要件(コピーの構成可能性やベクターの割り当て可能性など)がありましたが、C ++ 11では各コンテナー操作に関するきめ細かい要件が定義されています(セクション23.2)。

その結果、割り当てを必要としない特定の操作(構築およびpush_backそのような操作)のみを実行する限り、たとえば、コピー構築可能であるが割り当て不可能な型(constメンバーを持つ構造体など)をベクトルに格納できます。;でinsertはありません)。

私が疑問に思っているのは、これは標準が現在許可していることを意味するのvector<const T>でしょうか?const Tconstメンバーを持つ構造体のように、コピー構築可能であるが割り当て可能ではないタイプである必要がある理由はわかりませんが、何かを見逃している可能性があります。

(私が何かを見逃したかもしれないと思う理由の一部は、インスタンス化しようとするとgccトランクがクラッシュして燃えることですvector<const T>vector<T>、Tにconstメンバーがある場合は問題ありません)。

回答:


55

いいえ、アロケーターの要件では、Tは「非定数、非参照オブジェクト型」である可能性があるとされていると思います。

定数オブジェクトのベクトルでは、多くのことを行うことはできません。そして、const vector<T>とにかくほとんど同じでしょう。


何年も経った今でも、この素早い答えはコメントや投票を集めているようです。常に稼働しているわけではありません。:-)

したがって、いくつかの適切な参照を追加するには:

私が紙に書いているC ++ 03標準については、セクション[lib.allocator.requirements]の表31に次のように書かれています。

T, U any type

どのタイプも実際に機能したわけではありません。

したがって、次の標準であるC ++ 11は、[allocator.requirements]のドラフトで、現在は表27に記載されています。

T, U, C any non-const, non-reference object type

これは私が最初に記憶から上に書いたものに非常に近いです。これは、質問の内容でもあります。

ただし、C ++ 14(ドラフトN4296)では、表27に次のように記載されています。

T, U, C any non-const object type

おそらく、参照はおそらくオブジェクトタイプではないからですか?

そして今、C ++ 17(ドラフトN4659)では、次のようになっているのは表30です。

T, U, C any cv-unqualified object type (6.9)

したがってconst、除外されるだけでなく、も除外されvolatileます。とにかくおそらく古いニュース、そしてただの説明。


現在すぐ下にあるハワード・ヒナントの直接の情報も参照してください。


43
結論:const Tを保持するコンテナーは設計しませんでした。ただし、いくつか考えました。そして、私たちは偶然にそれをすることに本当に近づきました。私の知る限り、現在のこだわりaddressは、デフォルトのアロケーターのオーバーロードされたメンバー関数のペアです。Tがconstの場合、これら2つのオーバーロードは同じシグネチャを持ちます。これを修正する簡単な方法std::allocator<const T>は、オーバーロードの1つを特殊化して削除することです。
ハワードヒナント2011

4
@ HighCommander4:私は前向きではありません。libc ++では、協調アロケーターを使用してベクトル(空でないベクトルでも)を構築できます。私はそれで他に何もできません(非const)。それがあなたの「作品」の定義に合うかどうかはわかりません。また、無意識のうちに拡張機能を利用している場合も、前向きではありません。確かに、私はこの質問にもっと多くの時間を投資する必要があります。私は以前にそのような投資をしたことがありますが、それは数年前のことであり、その間に多くのことが変化しました。それが機能する場合、それは委員会側の設計によるものではありません。
ハワードヒナント2011

1
@ハワード:できることへの技術的な障害は考えられませんpush_back。しかし、それが設計上許可されていない場合は、それを行わない方がよいでしょう。ちょっと気になっただけ。
HighCommander4 2011

8
キャッシュは不変オブジェクトの可変コンテナであることが多く、ソートされたベクトルはマップの代替となることが多いため、constオブジェクトのベクトルがほとんど役に立たないことに同意しません。
クリスオールドウッド2013年

9
それは残念だ。とstd::vector<const T>非常によく似ているという理由だけで使用していましたが、それをconst std::vector<T>保持しているクラスにとって後者の悪影響はありませんでした。実際、std::vector<const T>私が使用するほとんどの場合、意味的に必要なのはまさにそれですvector。今、私は落とさなければなりませんconst-それが提供する信頼性とともに。
バイオレットキリン2016年

30

更新

私が2011年にコメントした、受け入れられた(そして正しい)答えの下で:

結論:保持するコンテナーは設計していませんconst T。私はそれにいくつかの考えを与えましたが。そして、私たちは偶然にそれをすることに本当に近づきました。私の知る限りでは、現在のこだわりのポイントは、オーバーロードのペアであるaddress場合には:デフォルトのアロケータでのメンバ関数Tconst、これら2つのオーバーロードは、同じシグネチャを持っています。これを修正する簡単な方法std::allocator<const T>は、オーバーロードの1つを特殊化 して削除することです。

今後のC ++ 17ドラフトでは、合法化されたように見えます。またvector<const T>誤って行ったと思います。:-)

P0174R0は、addressからオーバーロードを削除しstd::allocator<T>ます。 P0174R0std::allocator<const T>、その理論的根拠の一部としてサポートについて言及していません。

補正

以下のコメントで、TCは、addressオーバーロードが削除されるのではなく非推奨になることを正しく指摘しています。私の悪い。非推奨のメンバーは、std::allocatorが定義されている20.10.9には表示されませんが、代わりにセクションD.9に降格されます。私がこれを投稿したとき、私はこの可能性について第D章をスキャンすることを怠りました。

修正してくれてありがとうTC。私はこの誤解を招く答えを削除することを考えましたが、おそらく他の誰かが私と同じように仕様を誤解しないように、この修正をそのままにしておくのが最善です。


7
それはかなり面白いです!(今、私たちはそれについて本当に静かにする必要があり、誰にも気付かれることなくそれをC ++ 17に滑り込ませる必要があります:))
HighCommander4 2016

アロケータ要件の表それを完全に禁止しているだけではありませんか?とにかく、P0174R2(投票されたリビジョン)は非推奨になるだけで、削除はしませんaddress
TC

@TC:その通りです。訂正していただきありがとうございます。
ハワードヒナント2016

したがって、c ++ 2xは最終的に許可しますvector<const T>:)
MM

1
「結論:const Tを保持するコンテナーを設計しなかった」という答えは、コンテナーが「constT」を保持することを目標としていることを前提としています。ただし、ユーザーの目標は、コンテナーの内容に関係なく、コンテナーに対する操作を制限することであると主張することができます。たとえば、「back()」は「constT&」を返します。
ハンスオルソン2016年

8

これについてはすでに非常に良い答えがありますが、私はより実用的な答えを提供して、何ができるか、何ができないかを示すことにしました。

したがって、これは機能しません。

vector<const T> vec; 

他の回答を読んで、その理由を理解してください。そして、ご想像のとおり、これも機能しません。

vector<const shared_ptr<T>> vec;

Tはもはやconstではありませんが、sではなくsをvector保持してshared_ptrTます。

一方、これ機能します。

vector<const T *> vec;
vector<T const *> vec;  // the same as above

ただし、この場合、constはポイントされているオブジェクトであり、ポインター自体(ベクトルが格納するもの)ではありません。これは次と同等です。

vector<shared_ptr<const T>> vec;

どちらでも構いません。

しかしconst、式の最後に置くと、ポインターがに変わるconstため、以下はコンパイルされません。

vector<T * const> vec;

少し紛らわしいですが、私は同意しますが、あなたはそれに慣れています。


4

他の答えを補完する別のアプローチは、以下を使用することです。

vector<unique_ptr<const T>> vec;

それがあなたvecがそのアイテムの所有権だけを持っていることを強制したい場合です。または、アイテムを移動しvecたり、ある時点で移動したりするダイナミクスが必要な場合。

指摘したように、ポインタのconstセマンティクスは混乱を招く可能性がshared_ptrありunique_ptrますが、そうではありません。const unique_ptr<T>はconstポインターでunique_ptr<const T>あり、予想どおりconstポインターです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.