2012-03-21 8 views
2

올바르게 수행 할 수 있고 반복자를 원하는 포인터로 변환 할 수 없을 때 반복자 의미 체계를 통해 컨테이너/포인터에 효율적으로 액세스 할 수있는 클래스를 개발하려고합니다. 반복자 범위를 임시 버퍼에 복사하고 그 포인터를 반환하십시오. 표준 : 양단 큐의 반복자는 random_access_iterator_tag을 가지고 있기 때문에,반복자에 대한 클래스를 포인터로 변환하기

#include <cassert> 
#include <vector> 
#include <deque> 
#include <list> 

// General case copies data to temporary vector, in case iterators are from a list or otherwise. 
template < typename Iterator, typename tag = std::iterator_traits <Iterator>::iterator_category > 
class IteratorBuffer 
{ 
    typedef typename std::iterator_traits <Iterator>::value_type T; 

    std::vector <T> temp; 
public: 
    IteratorBuffer(Iterator begin, Iterator end) : temp(std::distance(begin, end)) 
    { 
     std::copy(begin, end, temp.begin()); 
    } 

    const T * data() { return temp.data(); } 
}; 

// Special case should be invoked if Iterator can safely be treated as a pointer to the range. 
template < typename Iterator > 
class IteratorBuffer < Iterator, std::random_access_iterator_tag > 
{ 
    typedef typename std::iterator_traits <Iterator>::value_type T; 

    const T * temp; 
public: 
    IteratorBuffer(Iterator begin, Iterator end) : temp(&*begin) { } 

    const T * data() { return temp; } 
}; 

int main(int argc, char ** argv) 
{ 
    std::vector <int> test1(10); 
    IteratorBuffer < std::vector <int>::iterator > temp1(test1.begin(), test1.end()); 
    // This should be pointing to the data in test1. 
    assert(temp1.data() == test1.data()); 

    std::list <int> test2; 
    for(int i = 0; i < 10; ++i) 
     test2.push_back(i); 
    IteratorBuffer < std::list <int>::iterator > temp2(test2.begin(), test2.end()); 
    // This must not point to the beginning iterator. 
    assert(temp2.data() != &*test2.begin()); 

    int test3[10]; 
    IteratorBuffer < int * > temp3(&test3[0], &test3[10]); 
    // This should point to the array. 
    assert(temp3.data() == &test3[0]); 

    std::deque <int> test4; 
    for(int i = 0; i < 10; ++i) 
     test4.push_back(i); 
    IteratorBuffer < std::deque <int>::iterator > temp4(test4.begin(), test4.end()); 
    // This must not point to the beginning iterator, not safe. 
    assert(temp4.data() != &*test4.begin()); 
} 

이 마지막 테스트에 실패 :이 작업을 수행하려면 나는 다음과 같은 프로그램을 작성했습니다.

일반적으로 올바르게 작동하도록 클래스를 작성하려면 어떻게해야합니까?

나는 내가 VC++ 2010

편집을 사용하고 언급해야한다고 가정 아담이 말하듯이 직접 수 없습니다 (I이 두려워). 자, 나는 이것을 할 수있게 해주는 자신의 특성을 정의하려고 시도하고있다. 내 시도는 아래를 참조하십시오 : 그들은 표준 : iterator_traits를 사용하는 것과 매우 유사하기 때문에

template < typename Iterator > 
struct IteratorTraits 
{ 
    enum { IsPointerCompatible = false }; 
    typedef typename std::iterator_traits <Iterator>::value_type T; 
}; 
template < typename T > 
struct IteratorTraits < T * > 
{ 
    enum { IsPointerCompatible = true }; 
    typedef T T; 
}; 
template < typename T > 
struct IteratorTraits < const T * > 
{ 
    enum { IsPointerCompatible = true }; 
    typedef const T T; 
}; 
//template < typename T > 
//struct IteratorTraits < typename std::vector <T>::iterator > 
//{ 
// enum { IsPointerCompatible = true }; 
// typedef T T; 
//}; 
//template < typename T, size_t N > 
//struct IteratorTraits < typename std::array < T, N >::iterator > 
//{ 
// enum { IsPointerCompatible = true }; 
// typedef T T; 
//}; 

나는 IteratorBuffer 클래스를 생략했습니다.

처음 두 특수화는 작동하지만 두 개의 주석이 달린 특성 구조체는 작동하지 않습니다. 내 특정 STL 구현에 의존하지 않고 이러한 기능을 어떻게 작성할 수 있습니까?

+0

'& * test2.begin()'이보기 흉하게 보입니다! – iammilind

+0

그것의 추악한 그러나 그것은 작동합니다 ... – dsharlet

+1

이것은 실제로 가능하지 않습니다 나는 두려워합니다. 유일한 가능성은'벡터 :: iterator'와 같은 특정 반복자를 전문화하는 것입니다. '벡터 :: reverse_iterator'는 안전하지 않습니다. –

답변

1

명시 적으로 포인터를 전문화 한 다음 모든 컨테이너 (알고있는 것)에서 반복자를 그런 방식으로 처리 할 수 ​​있습니다 (std::vector의 경우). 이것은 iterator가 포인터로 사용될 수 있다고 말하는 컨테이너의 일반적인 "특성"이 없기 때문에 나쁘지 않습니다. 이는 컨테이너 제공 업체가 명시 적으로 지정해야하는 보증입니다.


참고도 IteratorBuffer의 일반적 버전은 자동 적어도 순방향 반복자 범주를 가정하고 (이것은 배의 범위를 사용하는 바와 같이) 입력 전용 반복자 실패 할 것이다.

+0

답변 해 주셔서 감사합니다. 필자가 편집 한 것을보고, 당신이 설명하는 것을 구현하려고 시도하고 있지만, 특정 반복자 클래스에 대한 전문화를 정의하는 방법에 난처하지 않습니다. – dsharlet

+0

노력했지만 실패했습니다. 합리적인 표준 호환 솔루션이 없다고 믿는 것. 그러나 나는 더 많은 것을 시도 할 것이고 만약 내가 찾을 것이면 나는 그것을 여기에 게시 할 것이다. –