2009-06-27 3 views
0

컴파일 타임에 크기를 알 수있는 배열이 필요합니다. 나는 std :: vector 또는 boost :: array을 사용할 수 있다는 것을 알고있다. 하지만 그것이 내적으로 어떻게 작동하는지 가르쳐주지는 않습니다. 또한 이니셜 라이저를 사용하는 것 이외에 boost :: array에 항목을 추가하는 방법을 찾을 수 없습니다. generic 배열에 대해 다음 코드를 작성했습니다. 내 의도는 이터레이터, 템플릿 전문화 등을 익히는 것입니다. 다음은 코드입니다.반복자를 지원하는 일반 고정 크기 배열 구현

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 스타일의 배열이 집계되는 기준을 충족하는 경우의 C++에서

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

같은 것을, 당신은 초기화 목록 둘러싸인 중괄호 만 (현재)를 사용할 수 있습니다.

8.5.1.1 집계는 사용자 제공 생성자 (12.1)가 없거나 비공개 또는 비 정적 데이터 멤버가없는 배열 또는 클래스 (9 절) (11 절), 기본 클래스 없음 (10 절) 및 가상 함수 없음 (10.3).

현재 표준에서 사용하려는 경우 클래스에 해당 기능이 있어야합니다.다음 표준 (here 참조)에는 다른 유형을 허용하는 조항이 포함되어 있습니다.

2 - 코드에 함정이 있습니까?

다음은 하나입니다. 부스트 목록에 추가 할 수없는 이유는 항상 요소 수 (할당 된 크기)가 동일하기 때문입니다. 배열에서 요소를 추가 할 수 있지만 구성하는 동안 후드 아래에 여전히 10 개의 요소가 생성되었습니다. 사용자가 10 번 호출 된 기본 생성자를 기대하지 않으면 몇 가지 놀라운 결과가 발생할 수 있습니다.

2

boost :: array는 언어 기능을 사용합니다. 생성자가없는 struct는 초기화 목록을 사용할 수 있습니다. 자신 만의 생성자를 제공하면 초기화 목록을 사용할 수 없습니다.

또한 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

부스트/어레이 .hp보세요. 그것은 효과가있다. – rlbond

1

2 - 함정이 있습니까?

기본 크기 "크기 = 10"을 제거합니다. 10을 배열의 기본 크기로 만드는 것은 무엇입니까? 내가 우연히 발견 한 것은 우연히 크기를 벗어나서 그 크기보다 크다고 가정합니다.

요소 추가 및 C 스타일 초기화에 관해서는 두 가지를 모두 수행 할 수 있다고 생각하지 않습니다. 그것은 (나는) 객체가 아주 단순하게 배열 아래에 있기 때문에 부스트에서 작동합니다. 동적으로 크기를 재조정 할 수 없습니다. 이 클래스는 반복자 (및 :: sugar()와 같은 다른 설탕을 일반 배열에 추가하기 만합니다.