С++ библиотека, не основанная на итераторе?
Я был разочарован необоснованностью stl-итераторов и искал что-то более пригодное для использования. В частности, концепция, которую легче сопоставлять и фильтровать, и другую, которая также легче реализовать: в основном, С#/python/ruby /все-но-С++-типы.
Я наткнулся на Андрея Александреску Итератор должен уйти! в майкоте boostcon 2009 года, в котором он описывает концепцию диапазона, которая в значительной степени именно то, что я ищу, и многое другое.
Кто-нибудь знает, действительно ли что-то подобное было реализовано? Я знаю о boost:: range, но это не идеальное решение; он реализуется с точки зрения итераторов (что более запутанно и сложно, менее эффективно, менее общее, и делает запись вашей собственной, по крайней мере, такой же грязной, как реализация итератора). Тем не менее, это лучше, чем ничего. Там что-нибудь лучше?
Изменить: было много дискуссий о том, почему это вообще привлекательно. На итерации более четко объясняет мотивацию. Я понимаю связь с D - но это не должно отвлекаться от самого аргумента.
Ответы
Ответ 1
Прошло несколько лет, но похоже, что там есть библиотека, которая теперь реализует правильные последовательности функциональных стилей: С++ Streams.
Пример кода на главной странице проекта:
Суммирование первых 10 квадратов:
int total = stream::MakeStream::counter(1)
.map([] (int x) { return x * x; })
.limit(10)
.sum();
Ответ 2
Кажется довольно легко сделать сам - предполагая, что вы не против немного работы/ввода
Я еще не скомпилировал это, но что-то вроде этого должно немного сдвинуть вас вперед
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 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); }
для всех других контейнеров, просто убедитесь, что enumeration
определено и возвращает либо перечисление, либо editable_enumeration. Если другой контейнер уже реализует интерфейс итератора, то это должно работать
Теперь мы можем написать:
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";
Следует отметить одно огромное преимущество, которым придерживается концепция итератора. Это тот случай, когда запрашивается следующий элемент, когда has_next()
возвращает false. Для итераторов end() ++ - поведение (IIRC) undefined. Для перечисления он определен как throw std::runtime_error(...)
, который может быть хуже для некоторых людей.
Ответ 3
Может быть, это поможет вам: http://rangelib.synesis.com.au/.