2

필자는 iterator도 제공하는 자체 컨테이너 클래스를 작성하고 있습니다. 이 반복자는 참조 해제되어 원래 컨테이너의 하위 범위를 나타낼 수 있습니다.이 반복자는 다시 반복자를 얻을 수 있습니다.재귀를 중지하려면 템플릿 전문화를 제거 할 수 있습니까?

현재, 나는 Collection ("범위")에 역 참조 (boost::iterator_facade 사용) 템플릿 반복자 클래스 L!=0 경우 또는에 T& (저장 요소) L==0 경우를했습니다. 하나의 클래스에서 둘을 결합하여 가능한 적은 중복 코드가 필요합니까?

(1) boost::iterator_facade() 상속 클래스가 다른 인수를 나타납니다

template<typename T, int L> 
class CollectionIter : public boost::iterator_facade< 
     CollectionIter<T,L>, // type it selfe 
     Collection<T,L-1>, // value type 
     boost::random_access_traversal_tag, 
     Collection<T,L-1> > // deref. type 
{ 
public: 
    CollectionIter(T* ptr, const std::vector<int>& collectionSize_) 
     : pointer(ptr), collectionSize(collectionSize_) { } 
    T* element() { return pointer; } 
private: 
    friend class boost::iterator_core_access; 
    bool equal(const CollectionIter<T,L>& other) const { return pointer==other.pointer; } 
    auto dereference() const { return Collection<T,L-1>(pointer, collectionSize); } 
    void increment() { pointer = pointer + stepsize(); } 
    void decrement() { pointer = pointer - stepsize(); } 
    void advance(size_t i) { pointer = pointer + i*stepsize(); } 
    auto distance_to(const CollectionIter<T,L>& other) { return (other.pointer - pointer)/stepsize(); } 

    int stepsize() { return collectionSize.at(L); } 

    T* pointer; 
    const std::vector<int>& collectionSize; 
}; 

/* Groundlevel Collection: deref returns T& */ 
template<typename T> 
class CollectionIter<T,0> : public boost::iterator_facade< 
     CollectionIter<T,0>, 
     T, 
     boost::random_access_traversal_tag > 
{ 
public: 
    CollectionIter(T* ptr, const std::vector<int>& collectionSize_) 
     : pointer(ptr), collectionSize(collectionSize_) { assert(stepsize()==1); } 
    T* element() { return pointer; } 

private: 
    friend class boost::iterator_core_access; 
    bool equal(const CollectionIter<T,0>& other) const { return pointer==other.pointer; } 
    T& dereference() const { return *pointer; } 
    void increment() { pointer = pointer + stepsize(); } 
    void decrement() { pointer = pointer - stepsize(); } 
    void advance(size_t i) { pointer = pointer + i*stepsize(); } 
    auto distance_to(const CollectionIter<T,0>& other) { return (other.pointer - pointer)/stepsize(); } 

    int stepsize() { return collectionSize.at(0); } 

    T* pointer; 
    const std::vector<int>& collectionSize; 
}; 
+0

코드를 자세히 살펴 보지 않고 코드의 어딘가에'std :: conditional'을 적용하여 중복을 피하고 여전히 상속을받을 수있는 것처럼 보입니다. –

답변

1

나는 CollectionIter의 두 가지 버전에서만 세 가지 차이점을 참조하십시오. Johannes Schaub가 제안한대로 std::conditional으로 해결할 수 있습니다. 생성자에서

public std::conditional< (L > 0U), 
       boost::iterator_facade< 
       CollectionIter<T, L>, 
       Collection<T, L-1U>, 
       boost::random_access_traversal_tag, 
       Collection<T, L-1U> >, 
       boost::iterator_facade< 
       CollectionIter<T, 0U>, 
       T, 
       boost::random_access_traversal_tag > > 

(2) assert(stepsize()==1); 같은 단지 땅 (L == 0U) 버전에 존재한다. 당신은

assert((L > 0U) || (stepsize() == 1)); 

(3) 재귀 dereference() 방법은 접지 버전에서 정말 다른 수정할 수 있습니다. 내가 잘못 아니에요 경우에 따라서 전체 클래스가 될

template <int M = L, typename = std::enable_if_t<(M > 0U)>> 
    auto dereference() const 
    { return Collection<T, L-1U>(pointer, collectionSize); } 

    template <int M = L, typename = std::enable_if_t<(M == 0U)>> 
    T & dereference() const 
    { return *pointer; } 

을 다음과 같이 모두를 삽입 할 수 SFINAE의 전문가 모르겠지만 :

(미안 나는 std::size_tL을 변경했습니다)
template <typename T, std::size_t L> 
class CollectionIter : 
    public std::conditional< (L > 0U), 
       boost::iterator_facade< 
       CollectionIter<T, L>, 
       Collection<T, L-1U>, 
       boost::random_access_traversal_tag, 
       Collection<T, L-1U> >, 
       boost::iterator_facade< 
       CollectionIter<T, 0U>, 
       T, 
       boost::random_access_traversal_tag > > 
{ 
    public: 
     CollectionIter (T * ptr, const std::vector<int> & collectionSize_) 
     : pointer(ptr), collectionSize(collectionSize_) 
      { assert((L > 0U) || (stepsize() == 1)); } 

     T* element() { return pointer; } 

    private: 
     friend class boost::iterator_core_access; 

     bool equal (const CollectionIter<T, L> & other) const 
     { return pointer==other.pointer; } 

     template <int M = L, typename = std::enable_if_t<(M > 0U)>> 
     auto dereference() const 
     { return Collection<T, L-1U>(pointer, collectionSize); } 

     template <int M = L, typename = std::enable_if_t<(M == 0U)>> 
     T & dereference() const 
     { return *pointer; } 

     void increment() 
     { pointer = pointer + stepsize(); } 

     void decrement() 
     { pointer = pointer - stepsize(); } 

     void advance (size_t i) 
     { pointer = pointer + i*stepsize(); } 

     auto distance_to (const CollectionIter<T, L> & other) 
     { return (other.pointer - pointer)/stepsize(); } 

     int stepsize() 
     { return collectionSize.at(L); } 

     T * pointer; 

     const std::vector<int> & collectionSize; 
};