これは、イテレータを正確に実行できるとき、およびイテレータを必要なポインタに変換できないときに、コンテナ/ポインタに効率的にアクセスできるクラスを開発しようとしています。イテレーターの範囲を一時バッファーにコピーし、代わりにそのポインターを返します。 std ::両端キューのイテレータは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
Editを使用しています言及する必要がありますと仮定します。アダムが言うように、これは直接ことはできません(私はこれを恐れていました)。さて、私はこれを可能にする私自身の特性を定義しようとしています。私の試みは、以下を参照してください。彼らはSTD ::に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クラスを省略しました。
最初の2つの特殊化は機能しますが、2つのコメント付き特性文字列は機能しません。私の特定のSTL実装に依存することなく、動作するようにこれらをどのように記述しますか?
'&* test2.begin()'は醜いです! – iammilind
その醜いですが、それは動作します... – dsharlet
これは本当に私が恐れていることはありません。唯一の可能性は、 'ベクトル :: iterator'のような特定のイテレータに特化することです。 'ベクトル :: reverse_iterator'は安全ではありません。 –