Skip to content

Instantly share code, notes, and snippets.

@jeetsukumaran
Created February 18, 2010 02:33
Show Gist options
  • Save jeetsukumaran/307264 to your computer and use it in GitHub Desktop.
Save jeetsukumaran/307264 to your computer and use it in GitHub Desktop.
Sample C++/STL custom iterator
// Sample custom iterator.
// By perfectly.insane (http://www.dreamincode.net/forums/index.php?showuser=76558)
// From: http://www.dreamincode.net/forums/index.php?showtopic=58468
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cassert>
template <typename T>
class fixed_array
{
public:
typedef int size_type;
class iterator
{
public:
typedef iterator self_type;
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef int difference_type;
iterator(pointer ptr) : ptr_(ptr) { }
self_type operator++() { self_type i = *this; ptr_++; return i; }
self_type operator++(int junk) { ptr_++; return *this; }
reference operator*() { return *ptr_; }
pointer operator->() { return ptr_; }
bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
private:
pointer ptr_;
};
class const_iterator
{
public:
typedef const_iterator self_type;
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
const_iterator(pointer ptr) : ptr_(ptr) { }
self_type operator++() { self_type i = *this; ptr_++; return i; }
self_type operator++(int junk) { ptr_++; return *this; }
const reference operator*() { return *ptr_; }
const pointer operator->() { return ptr_; }
bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
private:
pointer ptr_;
};
fixed_array(size_type size) : size_(size) {
data_ = new T[size_];
}
size_type size() const { return size_; }
T& operator[](size_type index)
{
assert(index < size_);
return data_[index];
}
const T& operator[](size_type index) const
{
assert(index < size_);
return data_[index];
}
iterator begin()
{
return iterator(data_);
}
iterator end()
{
return iterator(data_ + size_);
}
const_iterator begin() const
{
return const_iterator(data_);
}
const_iterator end() const
{
return const_iterator(data_ + size_);
}
private:
T* data_;
size_type size_;
};
int main()
{
fixed_array<double> point3d(3);
point3d[0] = 2.3;
point3d[1] = 3.2;
point3d[2] = 4.2;
for(fixed_array<double>::iterator i = point3d.begin(); i != point3d.end(); i++)
{
std::cout << *i << " ";
}
std::cout << std::endl;
std::vector<double> vec;
std::copy(point3d.begin(), point3d.end(), std::back_inserter(vec));
for(std::vector<double>::iterator i = vec.begin(); i != vec.end(); i++)
{
std::cout << *i << " ";
}
std::cout << std::endl;
return 0;
}
@deiuch
Copy link

deiuch commented May 17, 2020

You are missing a destructor for your class.
T* data_ is assigned with new, so no implicite destruction.
It leaks !

There would not be any leak , because these iterator classes are going to be an inner class of the specific container.
Specific container has its own destructor and it can handle it by its own.

I think that this container will not have a way to do it since data_ is private. And you definitely should not allocate memory here if someone else is capable of deallocation. Just receive the pointer to memory in constructor then or take care of deallocation by yourself.

@deiuch
Copy link

deiuch commented May 17, 2020

And appropriate iterator_traits should be a good addition to this code :D

@nevzatseferoglu
Copy link

You are missing a destructor for your class.
T* data_ is assigned with new, so no implicite destruction.
It leaks !

There would not be any leak , because these iterator classes are going to be an inner class of the specific container.
Specific container has its own destructor and it can handle it by its own.

I think that this container will not have a way to do it since data_ is private. And you definitely should not allocate memory here if someone else is capable of deallocation. Just receive the pointer to memory in constructor then or take care of deallocation by yourself.

I mean that there is no leak from the point of iterator classes. Only allocation is happened by fixed_array class Therefore , you are right , there will be a leak , there is no destructor and also deallocation. Thanks for reminding.

@VirtualPirate
Copy link

Is there a way to reduce code. By some intelligent way. Because iterator and const_iterator are almost same except the const qualifications.

@LGoodacre
Copy link

LGoodacre commented Dec 6, 2020

@VirtualPirate

Is there a way to reduce code. By some intelligent way. Because iterator and const_iterator are almost same except the const qualifications.

You can have iterator inherit from const_iterator, and then run these overrides for iterator:

        value_type& operator*() { return const_cast<value_type&>(const_iterator::operator*()); }
        value_type* operator->() { return const_cast<value_type*>(const_iterator::operator->()); }    

The const_cast is what they use in STL, so I think it's safe :)

Looks like the typedefs have to stay, so it doesn't actually save that much code.

@amencke
Copy link

amencke commented Feb 7, 2021

excellent, thanks! nitpick: if you're implementing a container based on a fixed size C-style array, size_t would be a better choice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment