Eam*_*nne 12 c++ linq iterator functional-programming
受到Linq的污染,我不愿意放弃它.但是,对于某些事情,我只需要使用C++.
linq作为linq-consumer(即对我而言)的真正优势不在于表达树(操作起来很复杂),而是我可以轻松地混合和匹配各种功能.做的等价物.Where,.Select和.SelectMany, .Skip和.Take和.Concat存在C++ -风格的迭代器?
对于我编写的各种常用代码,这些都非常方便.
我不关心LINQ的细节,这里的关键问题是要能够在更高的层次来表达算法,而不是C++代码看起来像C#3.0.我希望能够表达"结果由每个序列的前n个元素串联形成",然后在需要新序列的地方重用这样的表达式 - 无需手动(并贪婪地)实例化中间体.
我正在研究(C#LINQ)类似C++头的库.
这是:http://code.google.com/p/boolinq/
我想得到任何反馈......
更新:
这是boolinq 2.0的新链接:https://github.com/k06a/boolinq
所有源代码都基于单头文件 - https://github.com/k06a/boolinq/blob/master/boolinq/boolinq.h
这是超短的:大约60种不同的操作不到800行!
我没有使用 LINQ 的具体经验,但Boost.Iterator库似乎接近您所指的内容。
这个想法是拥有函数(IIUC,在 LINQ 中,它们采用扩展方法的形式,但这不是基本的),采用迭代器和函数,将它们组合起来创建一个新的迭代器。
LINQ“哪里”映射到make_filter_iterator:
std::vector<int> vec = ...;
// An iterator skipping values less than "2":
boost::make_filter_iterator(_1 > 2, vec.begin())
Run Code Online (Sandbox Code Playgroud)
LINQ“选择”映射到make_transform_iterator:
using namespace boost::lambda;
//An iterator over strings of length corresponding to the value
//of each element in "vec"
//For example, 2 yields "**", 3 "***" and so on.
boost::make_transform_iterator(construct<std::string>('*', _1), vec.begin())
Run Code Online (Sandbox Code Playgroud)
它们可以组成:
//An iterator over strings of length corresponding to the value of each element
// in "vec", excluding those less than 2
std::vector<int> vec = ...;
boost::make_transform_iterator(construct<std::string>('*', _1),
boost::make_filter_iterator(_1 > 2, vec.begin())
)
Run Code Online (Sandbox Code Playgroud)
然而,这有一些烦人的事情:
make_xxx_iterator(some_functor, some_other_iterator)是xxx_iterator<type_of_some_functor, type_of_some_iterator>这就是为什么我在上面的代码中避免将结果分配make_xxx_iterator给变量。C++0x“自动”功能在那里会很受欢迎。
但是,C++ 迭代器仍然不能“单独”存在:它们必须成对出现才能发挥作用。所以,即使有了“auto”,它仍然很拗口:
auto begin = make_transform_iterator(construct<std::string>('*', _1),
make_filter_iterator(_1 > 2, vec.begin())
);
auto end = make_transform_iterator(construct<std::string>('*', _1),
make_filter_iterator(_1 > 2, vec.end())
);
Run Code Online (Sandbox Code Playgroud)
避免使用 lambda 会使事情变得冗长,但易于管理:
struct MakeStringOf{
MakeStringOf(char C) : m_C(C){}
char m_C;
std::string operator()(int i){return std::string(m_C, i);}
};
struct IsGreaterThan{
IsGreaterThan(int I) : m_I(I){}
int m_I;
bool operator()(int i){return i > m_I;}
};
typedef boost::filter_iterator<
IsGreaterThan,
std::vector<int>::iterator
> filtered;
typedef boost::transform_iterator<
MakeStringOf,
filtered
> filtered_and_transformed;
filtered_and_transformed begin(
MakeStringOf('*'),
filtered(IsGreaterThan(2), vec.begin())
);
filtered_and_transformed end(
MakeStringOf('*'),
filtered(IsGreaterThan(2), vec.end())
);
Run Code Online (Sandbox Code Playgroud)
(尚未)Boost.RangeEx 库在这方面很有前途,因为它允许将两个迭代器组合在一个范围内。就像是:
auto filtered_and_transformed = make_transform_range(
make_filter_range(vec, _1 > 2),
construct<std::string>('*', _1)
);
Run Code Online (Sandbox Code Playgroud)