Boost Range是否支持相邻元素转换?有无对应适配器?
Boost Range处理相邻元素转换的方案
好问题!Boost Range本身并没有直接提供专门用于转换相邻元素对的适配器,但我们有两种靠谱的解决办法:一种是用现有适配器组合实现,另一种是自定义适配你需求的适配器。
方案一:用现有适配器组合(推荐)
Boost Range的boost::adaptors::sliding适配器可以生成指定大小的滑动窗口,我们把窗口大小设为2,就能得到所有相邻元素对,再配合transformed适配器对每个窗口应用二元函数即可。
示例代码如下:
#include <vector> #include <iostream> #include <boost/range/adaptors.hpp> #include <boost/range/algorithm.hpp> int main() { std::vector<int> a = {1, 2, 3}; // 生成大小为2的滑动窗口,每个窗口包含相邻的两个元素 auto adjacent_windows = a | boost::adaptors::sliding(2); // 对每个窗口应用求和函数 auto result = adjacent_windows | boost::adaptors::transformed([](const auto& window) { return window[0] + window[1]; }); // 输出结果 boost::range::copy(result, std::ostream_iterator<int>(std::cout, ", ")); // 输出:3, 5, }
这个方法不需要自己写额外的迭代器或适配器,利用现有组件就能快速实现需求,代码可读性也不错。
方案二:自定义transform_adjacent适配器
如果你想要更直观的接口(就像你示例里写的a | boost::range::transformed([](int x, int y){return x+y;})这种形式),可以自己实现一个专门的适配器。
下面是完整的自定义适配器实现,基于Boost Range的迭代器适配器框架:
#include <vector> #include <iostream> #include <boost/range/adaptors.hpp> #include <boost/range/iterator_range.hpp> #include <boost/iterator/iterator_adaptor.hpp> // 自定义迭代器:遍历相邻元素对并应用二元函数 template <typename Iterator, typename BinaryFunc> class transform_adjacent_iterator : public boost::iterator_adaptor< transform_adjacent_iterator<Iterator, BinaryFunc>, Iterator, typename std::result_of<BinaryFunc(typename Iterator::value_type, typename Iterator::value_type)>::type, boost::use_default, typename std::result_of<BinaryFunc(typename Iterator::value_type, typename Iterator::value_type)>::type> { public: transform_adjacent_iterator() = default; transform_adjacent_iterator(Iterator it, BinaryFunc func) : transform_adjacent_iterator::iterator_adaptor_(it), func_(std::move(func)) {} private: friend class boost::iterator_core_access; // 解引用时获取当前元素和下一个元素,应用函数 typename transform_adjacent_iterator::reference dereference() const { Iterator next = this->base(); ++next; return func_(*this->base(), *next); } // 每次迭代向前移动一位 void increment() { ++this->base_reference(); } // 终止条件:当前迭代器的下一个元素是范围的末尾 bool equal(const transform_adjacent_iterator& other) const { Iterator next = this->base(); ++next; Iterator other_next = other.base(); ++other_next; return next == other_next; } BinaryFunc func_; }; // 适配器包装类,用于存储二元函数 template <typename BinaryFunc> struct transform_adjacent_adaptor { BinaryFunc func; explicit transform_adjacent_adaptor(BinaryFunc f) : func(std::move(f)) {} }; // 工厂函数,方便创建适配器 template <typename BinaryFunc> transform_adjacent_adaptor<BinaryFunc> transform_adjacent(BinaryFunc f) { return transform_adjacent_adaptor<BinaryFunc>(std::move(f)); } // 重载|运算符,让Boost Range识别我们的适配器 template <typename Range, typename BinaryFunc> auto operator|(Range&& r, transform_adjacent_adaptor<BinaryFunc> adaptor) { using Iterator = typename boost::range_iterator<Range>::type; using Iter = transform_adjacent_iterator<Iterator, BinaryFunc>; return boost::make_iterator_range( Iter(boost::begin(r), adaptor.func), Iter(boost::end(r), adaptor.func) ); } // 使用示例 int main() { std::vector<int> a = {1, 2, 3}; // 现在可以像你预期的那样使用了 auto result = a | transform_adjacent([](int x, int y) { return x + y; }); for (int val : result) { std::cout << val << ", "; } // 输出:3, 5, }
这个自定义适配器完全符合你想要的使用方式,接口更直观,适合频繁使用这类操作的场景。
内容的提问来源于stack exchange,提问作者bradgonesurfing
相关产品推荐
相关产品推荐

