올바르게 수행 할 수 있고 반복자를 원하는 포인터로 변환 할 수 없을 때 반복자 의미 체계를 통해 컨테이너/포인터에 효율적으로 액세스 할 수있는 클래스를 개발하려고합니다. 반복자 범위를 임시 버퍼에 복사하고 그 포인터를 반환하십시오. 표준 : 양단 큐의 반복자는 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 구현에 의존하지 않고 이러한 기능을 어떻게 작성할 수 있습니까?
'& * test2.begin()'이보기 흉하게 보입니다! – iammilind
그것의 추악한 그러나 그것은 작동합니다 ... – dsharlet
이것은 실제로 가능하지 않습니다 나는 두려워합니다. 유일한 가능성은'벡터 :: iterator'와 같은 특정 반복자를 전문화하는 것입니다. '벡터 :: reverse_iterator'는 안전하지 않습니다. –