我有一个类似于容器的对象(特别是Python C API to tuples)的遗留C API,我想用一个漂亮的C ++ 14 API包装,以便我可以使用迭代器。我该如何实施呢?
这里有更多细节。我们有以下现有的C API,无法更改:
Py_ssize_t PyTuple_GET_SIZE(PyObject *p);
PyObject* PyTuple_GET_ITEM(PyObject *p, Py_ssize_t pos);
void PyTuple_SET_ITEM(PyObject *p, Py_ssize_t pos, PyObject *o)
我们想要创建一个类,它允许您访问元组中元素的读/写迭代器。
前向只读迭代器不是很难定义。这就是我所拥有的:
class PyTuple {
private:
PyObject* tuple;
public:
PyTuple(PyObject* tuple) : tuple(tuple) {}
class iterator {
// iterator traits
PyObject* tuple;
Py_ssize_t index;
public:
iterator(PyObject *tuple, Py_ssize_t index) : tuple(tuple), index(index) {}
iterator& operator++() { index++; return *this; }
iterator operator++(int) { auto r = *this; ++(*this); return r; }
bool operator==(iterator other) const { return tuple == other.tuple && index == other.index; }
bool operator!=(iterator other) const { return !(*this == other); }
PyObject* operator*() { return PyTuple_GET_ITEM(tuple, index); }
// iterator traits
using difference_type = Py_ssize_t;
using value_type = PyObject*;
using pointer = PyObject**;
using reference = PyObject*&;
using iterator_category = std::forward_iterator_tag;
};
iterator begin() {
return iterator(tuple, 0);
}
iterator end() {
return iterator(tuple, PyTuple_GET_SIZE(tuple));
}
}
但是,我不太确定如何支持写入。我必须以某种方式让*it = pyobj_ptr
工作。通常,这可以通过将类型更改为PyObject*& operator*()
(以便它给出左值)来完成,但我不能这样做,因为元组"写"需要经过PyTuple_SET_ITEM
。我听说您可以使用operator=
来解决此案例,但我不确定是否应该使用通用引用(Why no emplacement iterators in C++11 or C++14?)或代理类(What is Proxy Class in C++),而不是确切地确定代码应该是什么样的。
答案 0 :(得分:3)
您正在寻找的内容基本上是代理参考。您不想取消引用PyObject*
,您想要取消引用本身可以为您提供PyObject*
的内容。这类似于vector<bool>
等类型的迭代器的行为方式。
基本上,您希望operator*()
能够为您提供以下内容:
class PyObjectProxy {
public:
// constructors, etc.
// read access
operator PyObject*() const { return PyTuple_GET_ITEM(tuple, index); }
// write access
void operator=(PyObject* o) {
PyTuple_SET_ITEM(tuple, index, o); // I'm guessing here
}
private:
PyObject* tuple;
Py_ssize_t index;
};