Jump to content
  • Advertisement
Sign in to follow this  
xSKOTTIEx

iterators?

This topic is 4860 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

ive been taking java all year, and i like how the iterator has a common interface. im working on my second game, and found that use of a common interface for iterators useful. however, in C++ (STL), there doesnt seem to be such a paradigm. am i missing anything? im using vector iterators: std::vector<cObject*>iterator iter = vectorList.begin(); iter++;... but that obviously does not seperate iterating through a list and the list itself, is there a way do a java like implementation? //java code Iterator iter = collection.iterator(); iter.next();

Share this post


Link to post
Share on other sites
Advertisement
Not to my knowledge [if I understand you correctly], to do that you'd require the STL iterators to inherit from some base interface. I think anyways, I am no expert. The closest you can come is something like this:


#include <vector>
#include <list>
#include <iostream>

using namespace std;


template <typename C>
void manual_print(C &c){
typename C::iterator it;

for (it=c.begin();it!=c.end();++it){
cout << *it << "\n";
}
}

int main(){

vector<int> foo;
list<float> bar;

foo.push_back(1);
foo.push_back(2);
foo.push_back(3);

bar.push_back(1.5);
bar.push_back(2.5);
bar.push_back(3.3);

manual_print(foo);
manual_print(bar);


}



Which should satisfy most cases where you don't know the actual container type [I think].

Share this post


Link to post
Share on other sites
More iterators (based on Telastyn's post):


#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename I>
void manual_print(I it, const I &end)
{
copy(it, end, ostream_iterator<typename iterator_traits<I>::value_type>(cout));
endl(cout);
}

template <typename C>
void manual_print(const C &c)
{
manual_print(c.begin(), c.end());
}

int main()
{
// Using an actual container:
manual_print(string("Hello World! (1)"));

// Using character pointers:
const char * message = "Hello World! (2)";
manual_print(message, message+16);

return 0;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by xSKOTTIEx
however, in C++ (STL), there doesnt seem to be such a paradigm. am i missing anything?


Indeed I’ve think you've missed the point completely, C++ favour's & foster's generic programming via static polymorphism (compile-time binding) using templates which is much more efficient aswell as providing type-safety, the standard library has a set of generic algorithms that take iterators to query and/or modify containers with-out knowing which container is being used and with-out breaking encapsulation.

The C++ standard defines a set of "concepts" each of which defines a set of requirements that concrete types model or are said to be "a model of" where as java defines interfaces that types must implement how-ever in C++ you don't write concepts in code (people are trying to make this happen how-ever) and a concept can define requirements which are not just signature oriented like interfaces for example they can specify time complexities e.g. "such and such operation takes amortized logarithmic time", as well as other kinds of requirements like state invariants, required operations of a type.

For example the C++ standard defines the Iterator concepts: Trivial Iterator, Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator.

Anyways if you want to work generically use the standard library algorithms instead of explicit loop code, for example instead of using a for loop use std::for_each (better yet another more specific algorithm like std::copy).

Quote:
Original post by xSKOTTIEx
is there a way do a java like implementation?


My response to that is it's unnecessary in C++, as i've mentioned to work generically (meaning being able to substitute code with almost any other container) use the standard library algorithms they work with iterators generically.

[Edited by - snk_kid on April 26, 2005 4:36:45 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Alpha_ProgDes
why not just make a class that implements an Iterator.
I don't think it's that hard.


Indeed it's not that hard, if you're willing to pay for the virtual function calls on each "next" and "hasNext".


#include <iostream>
#include <typeinfo>
#include <stdexcept>

#include <vector>
#include <map>

class NoSuchElementException :
public std::runtime_error
{
public:
NoSuchElementException() :
std::runtime_error("NoSuchElementException")
{}

NoSuchElementException(const std::string& message) :
std::runtime_error(message)
{}

};

template<class T>
class JavaIteratorImplBase
{
public:
virtual bool hasNext() const = 0;
virtual T& next() = 0;
virtual JavaIteratorImplBase* clone() = 0;
virtual ~JavaIteratorImplBase() {}
};

template<class C>
class JavaIteratorImpl :
public JavaIteratorImplBase<typename C::value_type>
{
typedef typename C::iterator iterator;
typedef typename C::value_type value_type;

iterator begin_, end_;

public:
JavaIteratorImpl(C& c) : begin_(c.begin()), end_(c.end()) {}

bool hasNext() const { return begin_ != end_; }

value_type& next()
{
if( begin_ == end_ )
throw NoSuchElementException();

value_type& ref = *begin_;
++begin_;
return ref;
}

JavaIteratorImpl* clone() { return new JavaIteratorImpl(*this); }

};

template<class T>
class JavaIterator
{
JavaIteratorImplBase<T>* impl_;

public:
template<class C> JavaIterator( C& c ) :
impl_( new JavaIteratorImpl<C>(c) )
{}

~JavaIterator() { delete impl_; }

JavaIterator( const JavaIterator& rhs ) :
impl_( impl_->clone() )
{}

JavaIterator& operator=( const JavaIterator& rhs )
{
JavaIterator tmp( rhs );
std::swap( impl_, rhs.impl_);
return *this;
}

bool hasNext() const { return impl_->hasNext(); }
T& next() { return impl_->next(); }
};



int main()
{
std::vector<int> v(10);

JavaIterator<int> itor(v);

while(itor.hasNext())
std::cout << itor.next() << std::endl;
}



Of course, remember that if you want to iterate over a std::map<int,int>, you'll need a JavaIterator<std::pair<int,int> >.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!