C++ non-iterator based range library?

I've been frustrated by the unhandiness of stl iterators and am looking for something more usable. In particular, a concept that is easier to map and filter, and one that is easier to implement too: basically C#/python/ruby/everything-but-C++ style enumerations.

I came across Andrei Alexandrescu's Iterator's must go! boostcon keynote of 2009 in which he describes a range concept that pretty much is exactly what I'm looking for and much more.

Does anybody know if something like this was actually implemented? I know of boost::range, but that's not an ideal solution; it's implemented in terms of iterators (which is more confusing and complex, less efficient, less general, and makes writing your own one at least as messy as implementing an iterator). Still, it's better than nothing. Is there anything better out there?

Edit: there's been lot's of discussion as to why this is at all attractive. On iteration explains the motivation more clearly. I realize the link to D - but that shouldn't distract from the argument itself.

Answers


Seems pretty easy to do yourself -- assuming you don't mind a bit of work/typing

I haven't compiled this yet but something like this should move you a bit along

template< typename T>
class enumeration : boost::noncopyable {
virtual T& next() = 0;
virtual bool has_next() = 0;
};

template< typename T>
class editable_enumeration : public enumeration<T> {
virtual void remove() = 0;
}

//That was simple enough, now for adapting the std containers we
//will use the iterator interface already exposed. For new classes,
//we can implement iterators in any way we want. (e.g. copy python or java)

template < class C >
class const_std_enumeration : public enumeration<C::value_type>
{
protected:
C::const_iterator iter_;
C::const_iterator end_;

public:
typedef C::value_type value_type;

const_std_enumeration( C const& c) :
iter_(c.begin()), end_(c.end()) { } //c++0x use std::begin(c), std::end(c) instead

virtual value_type& next() { if(iter_!=end_) return *iter_++; throw std::runtime_error("No more elements"); }
virtual bool has_next() { return iter_!=end_; }
};

template < class C>
class std_enumeration : public enumeration<C::value_type>
{
protected:
C& c_;
C::iterator iter_;
C::iterator end_;

public:
typedef C::value_type value_type;

std_enumeration( C& c) :
c_(c), iter_(vector.begin()), end_(vector.end()) { }

virtual value_type& next() { if(v_!=end_) return *iter_++; throw std::runtime_error("No more elements"); }
virtual bool has_next() { return iter_!=end_; }
virtual remove() { iter_ = c_.erase(iter_); }
};


//Since we can't add methods to std containers, we will use an
//overloaded free-function `enumeration` to get enumerations from ANY container
//We could use `auto_ptr` or `unique_ptr`, but for simplicity's sake, I'm
//just using raw pointers

template < class C >
editable_enumeration<C::value_type>* enumeration( C&c ) { return new std_enumeration<C>(c); }

template < class C >
enumeration<C::value_type>* enumeration( C const& c ) { return new const_std_enumeration<C>(c); }

for all other containers, merely ensure that enumeration is defined and returns either an enumeration or editable_enumeration. If you other container already implements the iterator interface, then this should work

We can now write:

template<typename T>
bool contains( enumeration<T>* e, T const& t) {
while(e->has_next())
  if ( t == e->next() )
    return true;
return false;
}
...
std::vector<int> v = getIntVector();
if( contains( enumeration(v), 10 ) ) std::cout<<"Enumeration contains 10\n";
std::list<int> l = getIntList();
if( contains( enumeration(l), 10 ) ) std::cout<<"Enumeration contains 10\n";

It should be noted one huge advantage the iterator concept holds over this is the case where the next element is requested when then has_next() would return false. For iterators, end()++ is (IIRC) undefined behavior. For teh enumeration, it is defined to throw std::runtime_error(...) which may be worse for some people.


May be this one will help you: http://rangelib.synesis.com.au/ .


It's been a few years, but it looks like there's a library out there that implements proper functional style sequences now: C++ Streams.

Code sample from the project's homepage:

Summing the first 10 squares:

int total = stream::MakeStream::counter(1)
    .map([] (int x) { return x * x; })
    .limit(10)
    .sum();

Need Your Help

Google Analytics Page Load Times vs Pingdom Page Load Times.

wordpress google-analytics pingdom

I am examining the page load time numbers in GA and Pingdom. My avg via pingdom is consistently 3 seconds, or around that. My page load time in GA is consistently around 10 seconds. Can anyone expl...

XML to object mapping using xstream

java xml xstream

I want to map the following XML to the following java object. Probably i need to override the reflection function of stream. I tried the ReflectionConverter, but it didn't work for me. Any help wil...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.