过载->操作员通过代理转发成员访问 [英] Overload -> operator to forward member-access through Proxy
问题描述
我正在尝试将Python PyObject*
包装在Object
类中.
在Python中,所有内容均为PyObject*
.
列表是PyObject*
,列表中的每个项目本身都是PyObject*
.
甚至可能是另一个列表.
等
I'm trying to wrap a Python PyObject*
in an Object
class.
In Python, everything is a PyObject*
.
A list is a PyObject*
, and each item in the list is itself a PyObject*
.
Which could even be another list.
etc.
我正在尝试通过代理模式允许fooList[42] = barObj
样式语法(这里).
I'm trying to allow fooList[42] = barObj
style syntax by means of a Proxy pattern (here).
现在我可以正常工作了,我想扩展它,以便可以将fooList[42]
用作Object
.具体来说,我希望能够处理...
Now that I have that working, I want to extend it so that fooList[42]
can be used as an Object
. Specifically I want to be able to handle...
fooList[42].myObjMethod()
fooList[42].myObjMember = ...
Object
有很多方法,目前fooList[42].myObjMethod()
首先将fooList[42]
解析为Proxy
实例(例如tmpProxy
),然后尝试tmpProxy.myObjMethod()
.
Object
has a lot of methods, and currently fooList[42].myObjMethod()
is going to first resolve fooList[42]
into a Proxy
instance, say tmpProxy
, and then attempt tmpProxy.myObjMethod()
.
这意味着我必须做
void Proxy::myObjMethod(){ return wrapped_ob.myObjMethod(); }
即很难通过Proxy
手动中继Object
的每个方法.
i.e. manually relay each of Object
's methods through Proxy
, which is ugly.
我看不到任何完美的解决方案(请参见上面的链接答案),但我很乐意使用:
I can't see any perfect solution (see the above linked answer), but I would be happy to use:
fooList[42]->myObjMethod()
...作为一种妥协,看到-> (而不是.
不能超载).
... as a compromise, seeing as -> can be overloaded (as opposed to .
which cannot).
但是,我找不到任何有关operator->
重载的文档.
However, I can't find any documentation for overloading operator->
.
我最好的猜测是它必须返回一个指向某个对象的指针(例如pObj
),而C ++将调用pObj->whatever
.
My best guess is that it must return a pointer to some object (say pObj
), and C++ will invoke pObj->whatever
.
以下是我尝试的实现.但是,我遇到了获取类型为Object的临时对象的地址" 警告.
Below is my attempted implementation. However, I'm running into a 'taking the address of a temporary object of type Object' warning.
在我的Object
类中,我有:
const Object operator[] (const Object& key) const {
return Object{ PyObject_GetItem( p, key.p ) };
}
请注意,"const Object&" 遇到获取类型为Object的临时对象的地址" .
NOTE that 'const Object&' runs into 'taking the address of a temporary object of type Object' warning.
class Proxy {
private:
const Object& container;
const Object& key;
public:
// at this moment we don't know whether it is 'c[k] = x' or 'x = c[k]'
Proxy( const Object& c, const Object& k ) : container{c}, key{k}
{ }
// Rvalue
// e.g. cout << myList[5] hits 'const Object operator[]'
operator Object() const {
return container[key];
}
// Lvalue
// e.g. (something = ) myList[5] = foo
const Proxy& operator= (const Object& rhs_ob) {
PyObject_SetItem( container.p, key.p, rhs_ob.p );
return *this; // allow daisy-chaining a = b = c etc, that's why we return const Object&
}
const Object* operator->() const { return &container[key]; }
// ^ ERROR: taking the address of a temporary object of type Object
};
想法是允许使用myList[5]->someMemberObj = ...
样式语法.
The idea is to allow myList[5]->someMemberObj = ...
style syntax.
myList[5]
解析为Proxy
实例,该实例包装了Object
(myList
的第六个元素).我们称之为myItem
.
myList[5]
resolves as a Proxy
instance, which is wrapping an Object
(the sixth element of myList
). Let's call it myItem
.
现在,我希望someProxy->fooFunc()
或someProxy->fooProperty
分别调用myItem.fooFunc()
或myItem.fooProperty
.
Now I want someProxy->fooFunc()
or someProxy->fooProperty
to invoke myItem.fooFunc()
or myItem.fooProperty
respectively.
我遇到了获取类型为Object的临时对象的地址" 警告.
推荐答案
如果可以更改Object
,则可以添加
If you can change Object
, you may add
class Object {
public:
// other code
const Object* operator -> () const { return this; }
Object* operator -> () { return this; }
};
还有您的Proxy
Object operator->() { return container[key]; }
例如,
myObj[42]->myFoo = ...
主要等同于
Proxy proxy = myObj[42];
Object obj = proxy.operator ->();
Object* pobj = obj.operator ->(); // so pobj = &obj;
pobj->myFoo = ...
这篇关于过载->操作员通过代理转发成员访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!