【发布时间】:2020-11-18 10:08:28
【问题描述】:
我正在尝试将一个对象传递给boost::adaptors::transformed。但是,这似乎只有在该对象的类定义了begin 和end 的const 版本时才有效。然而,这对我来说不是这样,因为迭代这个类的对象会修改对象本身的内部状态。这是一个使用虚拟类 Vector 的最小示例,它仅公开非 const 版本 begin 和 end 或其 _v 成员,我可以更改什么来使其工作?
#include <initializer_list>
#include <vector>
#include <boost/range/adaptors.hpp>
template<typename T>
class Vector
{
public:
using value_type = typename std::vector<T>::value_type;
using reference = typename std::vector<T>::reference;
using iterator = typename std::vector<T>::iterator;
Vector(std::initializer_list<T> init)
: _v(init)
{}
iterator begin() { return _v.begin(); }
iterator end() { return _v.end(); }
private:
std::vector<T> _v;
};
int main()
{
Vector<int> v{1, 2, 3, 4};
auto t = [](int i){ return 2 * i; };
auto range(v | boost::adaptors::transformed(t)); // does not compile
}
【问题讨论】:
-
如果你仍然想继续错误的设计(在迭代过程中修改集合,肯定会带来错误)让你向量
mutable std::vector<T> _v;并添加 const 版本。无论如何,您为什么认为 boost 作者会增加限制以仅使用常量迭代器?强烈建议您不要在不复制数据的情况下在 C++ 中使用函数式样式。 2. 使用你的 Haskell 或其他任何东西。 -
附言。您只需要:
#include <array> #include <iostream> int main(int argc,const char **argv) { std::array<int,4> src = {1, 2, 3, 4}; std::array<int,4> dst; for(std::size_t i=0; i < src.size(); i++) { dst[i] = src[i] << 1; } return 0; } -
@VictorGubin 你会认为 OP 知道如何做到这一点。也许您已经看到了我没有看到的 OP 之前提出的问题,但是没有理由假设仅仅对这个问题有很大的无知。
-
@sehe - 我不认为 OP 有任何无知。我认为他试图使用命令式编程语言作为函数式编程语言。它带来了真正的过度设计。更复杂的转换可以用同样的简单循环来完成。
-
P.S.我对范围概念的理解 - 改进诸如 find_if 之类的操作,其中 lambda 可用于按字段搜索容器中的结构。或将一个对象的向量转换为向量或另一个对象。恕我直言,使用 lambda 转换对象是一种设计变态。也许对于一些功能齐全的 PL 来说还可以,但不确定 C++ 是否还可以。实际上是一个疯狂的逻辑,代码在几个月内没有人可以阅读,包括作者在内,编译器无法优化。
标签: c++ boost boost-range