2009-06-27 14 views
0

コンパイル時にサイズがわかっている配列が必要です。私はstd :: vectorまたはboost :: arrayを使用できることを知っています。しかし、それは私が内部的にどのように働くか教えていません。また、イニシャライザを使用する以外に、boost :: arrayにアイテムを追加する方法が見つかりませんでした。私はジェネリック配列のために次のコードを書いています。私の意図は後など、イテレータに慣れるためにテンプレート特殊である上記のコードはうまく動作するコードイテレータをサポートする一般的な固定サイズの配列を実装する

template<typename T> 
struct iterator_traits 
{ 
    typedef T   value_type; 
    typedef T&   reference_type; 
    typedef T*   iterator; 
    typedef const T* const_iterator; 
    typedef std::reverse_iterator<iterator> reverse_iterator; 
}; 

template<typename T> 
struct iterator_traits<T*> 
{ 
    typedef T*   value_type; 
    typedef T*&   reference_type; 
    typedef T**   iterator; 
    typedef const T  const_iterator; 
    typedef std::reverse_iterator<iterator> reverse_iterator; 
}; 

template<typename T, size_t size = 10> 
class Array 
{ 
    public: 

     typedef typename iterator_traits<T>::value_type  value_type; 
     typedef typename iterator_traits<T>::reference_type reference_type; 
     typedef typename iterator_traits<T>::iterator   iterator; 
     typedef typename iterator_traits<T>::const_iterator const_iterator; 
     typedef typename iterator_traits<T>::reverse_iterator reverse_iterator; 

     Array() : lastIndex(0) { 
     } 

     void add(value_type element) { 
      if(lastIndex >= size) 
       throw std::out_of_range("Array is full"); 
      array_[lastIndex++] = element; 
     } 

     reference_type at(unsigned int index){ 
      if(index < size) 
       return array_[index]; 
      else 
       throw std::out_of_range("Invalid index"); 
     } 

     size_t capacity(){ 
      return size; 
     } 

     iterator begin(){ 
      return array_; 
     } 

     iterator end(){ 
      return array_ + size; 
     } 

     const_iterator begin() const{ 
      return array_; 
     } 

     const_iterator end() const{ 
      return array_ + size; 
     } 

     reverse_iterator rbegin() { 
      return reverse_iterator(end()); 
     } 

     reverse_iterator rend() { 
      return reverse_iterator(begin()); 
     } 

    private: 

     value_type array_[size]; 
     unsigned int lastIndex; 
}; 

です。以下は私の質問です

1 - boost :: arrayのような配列を作成するにはどうしたらいいですか?何かのように

Array<int> ints = { 10, 12 }; 

2 - コードに落とし穴がありますか?

3 - 私は、形質のポインタ型のための特殊化を使用しなければなりませんでした。それがベストプラクティスですか?

4 - イテレータパターンが正しく実装されているかどうかを確認します。

どのような考えもすばらしいでしょう!

+1

std :: iterator_traits(#include )は既にポインタ用に特化されていますので、独自のポインタを用意する必要はありません。 –

+1

ブーストに何も追加できないという意味はどうですか?配列ですか? – GManNickG

答えて

2

1 - どうすればboost :: arrayのような配列を作成できますか? C++では

Array<int> ints = { 10, 12 }; 

ような何かあなたの構造体、共用体またはCスタイルの配列が集約さの基準を満たしている場合、あなただけの(現在は)かっこ囲まれた初期化子リストを使用することができます。

8.5.1.1集約は、ユーザー提供のコンストラクタ(12.1)を持たない配列またはクラス(9.1)であり、プライベートまたは保護された非静的データメンバーはありません(11 )、基本クラスなし(第10項)、仮想関数なし(10.3)である。

現在の標準で使用する場合は、クラスにこれらの機能を持たせる必要があります。次の規格(hereを参照)には、他のタイプがそうすることを可能にする規定が含まれています。

2 - コードに落とし穴がありますか?

これは1つです。ブーストリストに追加できない理由は、常に同じ要素数(割り当てられたサイズ)を持つからです。配列内に要素を追加することはできますが、構築中にフードの下に10要素を作成しています。これは、ユーザが10回呼ばれるデフォルトのコンストラクタを期待していない場合に、驚くべき結果につながる可能性があります。

2

boost :: arrayは、言語の機能を使用します。コンストラクタを持たない構造体では、初期化リストを使用できます。独自のコンストラクタを提供する場合は、初期化リストを使用することはできません。

また、iterator_traitsが間違っています。あなたのコードは次のようなものでなければなりません

// type definitions 
    typedef T    value_type; 
    typedef T*    iterator; 
    typedef const T*  const_iterator; 
    typedef T&    reference; 
    typedef const T&  const_reference; 
    typedef std::size_t size_type; 
    typedef std::ptrdiff_t difference_type; 

iterator_traitsはイテレータの特性です。また、ポインタをイテレータとして使用することもできます。 STLはこれを明示的に許可します。

+0

私はこれを試しました。しかし、型がポインタの場合は動作しません。これがイテレータの特性を作った理由です。 –

+0

boost/array.hppを見てください。それは動作します。 – rlbond

1

2 - 落とし穴がありますか?

私はデフォルトサイズ "サイズ= 10"を取り除きます。 10を配列のデフォルトサイズにする理由は何ですか?代わりに、私が起こっていることは、間違ってサイズから離れて、それがそれより大きいと仮定している人です。

要素の追加とCスタイルの初期化に関して、私はその両方を行うことはできないと考えています。これは、オブジェクトが非常に単純に、カバーの下にある配列であるため(私が信じる)、ブーストで機能します。動的にサイズ変更することはできません。クラスは単純な配列にイテレータ(および他の砂糖のような:: at())を追加するだけです。

関連する問題