我对stl迭代器的不当感到沮丧,我正在寻找更有用的东西。特别是,一个更易于映射和过滤的概念,以及一个更容易实现的概念:基本上是C#/ python / ruby / everything-but-C ++样式枚举。
我遇到了Andrei Alexandrescu在2009年的 Iterator's must go! boostcon主题演讲,其中他描述了一个范围概念,几乎正是我正在寻找的东西等等。
有人知道这样的事情是否真的实现了?我知道boost :: range,但这不是一个理想的解决方案;它是根据迭代器实现的(它更混乱,更复杂,效率更低,更不通用,并且使编写自己的迭代器至少与实现迭代器一样混乱)。不过,它总比没有好。那里有什么更好的吗?
编辑: 关于为什么这一点很有吸引力的讨论已经很多了。 On iteration 更清楚地解释了动机。我意识到与D的联系 - 但这不应该分散论点本身。
答案 0 :(得分:5)
看起来很容易做到 - 假设你不介意做一些工作/打字
我还没有编译过这个,但是这样的事情应该会让你感觉有点
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); }
对于所有其他容器,只需确保定义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)未定义的行为。对于枚举,它定义为throw std::runtime_error(...)
,对某些人来说可能更糟。
答案 1 :(得分:2)
可能这个会帮助你:http://rangelib.synesis.com.au/。
答案 2 :(得分:1)
已经有几年了,但看起来现在有一个库可以实现正确的功能样式序列:C++ Streams。
来自项目主页的代码示例:
总结前10个方块:
int total = stream::MakeStream::counter(1)
.map([] (int x) { return x * x; })
.limit(10)
.sum();