2013-03-03 10 views
7

C++標準ライブラリには、コンテナオブジェクトのインタフェースを指定するためのさまざまな「概念」が用意されています。例えば、std::vectorは、Container,Sequence,RandomAccessContainerおよびReversibleContainerという概念を実装しています。これは有用であろうC++連続シーケンスの概念

static_cast<void*>(&some_sequence[N]) == static_cast<void*>(&some_sequence[0] + N)>

:よう

コンセプトがありますが、要素間の連続したメモリを保証Sequenceを記述し、C++ 03やC++ 11のいずれかで指定されましたなぜなら、コンテナを連続したメモリバッファを必要とする任意の関数(たとえば、std::istream::read)で使用できるかどうかを示すためです。

私は実際には、唯一の std::vectorは(と私はC++ 11で std::stringを考えて)実際に根本的な連続したバッファを保証する、ということを知っている

- Aを示しているが、そこにこの保証はstd::vectorに固有であるか、または定義された「コンセプト」連続したメモリを提供する汎用のSequenceクラス?

+4

'std :: array';) – Zeta

+8

私が知る限り、そのような概念はありません。 std :: vector'、 'std :: string'と' std :: array'は '[0、c]の' i'に対して 'c.data()+ i ==&c [i]' 。サイズ()) '。 – Xeo

+1

@ Xeo:そうです。概念はなく、要素(または 'char_type's)が*「連続して格納されている」という要件だけです*。 – Zeta

答えて

0

(23.2.4.1)はC++ 03、のみstd::vector保証より:ベクターの

要素があれば、V Tは、いくつかの あるベクトルであることを意味し、連続 に格納されていますbool以外のタイプの場合、 身元確認& v [n] == & v [0] + n for すべて0 < = n < v.size()。

C++ 11には、固定サイズの配列を囲むラッパーで、同じプロパティを持つstd :: arrayが追加されています。私は、コンテナにそのような特性があるかどうかを知る方法はないと思います。

1

私は自己がこの機能を何度も果たすタイプを識別しなければならないことが分かりました。私はこのような特別な「コンセプト」を発明することがエレガントであるかどうかはわかりません(抽象的ではない記憶を含む概念であると想像してください)。

一方、実際には、をこのコンセプト/要件を純粋な構文要件に翻訳して、後方に歩いてみましょう。私たちが標準に制限されている場合、連続性を保証する(またはほぼ保証する)クラスは何ですか?関連性の順に:すべてのこれらの

std::vector<T> 
T[N] // !! 
std::array<T, N> 
std::string 
std::initializer_list<T> 
std::valarray<T> 

std::vectorstd::arraystd::string.data()と呼ばれるメンバ関数を持っています。したがって、これで十分であれば、メンバー.data() -> T*の存在を利用して連続したメモリを示すことができます。

1)型が連続していない場合は、構文エラーを発生させるためにメンバ関数.data()を使用する努力を行います

2つのオプションがあります。 (たとえば、t[0]*t.data()に置き換えた場合は難しくありません)

2).data()にある種のSFINAEを使用してください。

template<class ContiguousSequence, typename = decltype(std::declval<ContigiousSequence>().data())> 
void fun(ContiguousSequence&& s){...} // this function will only work with contiguous data 

また、C++ 17は、.data()との全てのタイプにそれを一般化し、さらにT[N]std::initializer_list<T>ためオーバーロードstd::dataを有しています。 ....data()を上記のstd::data(...)に置き換えることができます。

結論は、私はそれが良い慣例であると思い、その型は、値型連続する 要素へのポインタを返す(C++ 11または.data()data 機能を有している場合。

(あなたがstd::data(std::valarray<T>&)に過負荷をかけない限り、[OK]を、std::valarray<T>について?それは、何が動作しません。しかし、いずれにせよstd::valarrayを使用しています?それはC++のかなり放棄したコーナーで、私は思う)。最後

、のためのノートたとえば、明らかにstd::map以下で明らかにstd::dequeには.data()(またはstd::data(...))機能がありません。 boost::multi_array<..., N>.data()のメンバーを持ち、配列要素へのポインタを返します。順序が明白ではないため、連続した配列であるかどうかは不明ですが、ある意味では連続したメモリの割り当てでもあります。

EDIT: 2つの現在、この問題に対処する提案(しかし、イテレータのレベルで)http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3884.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4284.html

3

"連続コンテナは、" C++ 17にspecifedさがあります。 $23.2.1/13 General container requirements [container.requirements.general]から:

連続コンテナ部材型イテレータとconst_iteratorの隣接イテレータ([iterator.requirements.general])は、ランダム・アクセス・イテレータ([random.access.iterators])とを支持する容器です。

そして "連続イテレータ" について、$24.2.1/5 In general [iterator.requirements.general]:さらにN、積分値の要件を満たし、dereferenceableイテレータと(+ n)を値

イテレータ、*(+ N )は*(addressof(* a)+ n)と等価であり、連続イテレータと呼ばれます。

std::vector<bool>を除く)std::vectorstd::arraystd::basic_stringは連続容器です。

+0

ニース。どのコンテナが連続しているかが明示されていますか?私は 'std :: valarray'とplainがリストにあるはずだと思います。プレーンな配列はどうですか? –

+2

@ JohanLundberg私は標準を検索しようとしたが、私の答えに記載されている3つのコンテナだけが "連続コンテナ"と思われる。 'std :: valarray'とプレーンな配列は"連続 "ですが、"コンテナ "ではなく"連続したコンテナ "ではありません。 – songyuanyao