lundi 29 décembre 2014

How to overload -> operator in C++

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.


I'm trying to allow fooList[42] = barObj style syntax by means of a Proxy pattern (here).


Now that I have that working, I want to extend it. Object has a lot of methods, and currently fooList[42].myMethod() is going to first resolve fooList[42] into a Proxy instance, say tmpProxy, and then attempt tmpProxy.myMethod().


This means I would have to relay all Object's methods through Proxy (i.e. I would have to create the corresponding method in Proxy that relays), which is ugly.


I can't see any perfect solution (see the above linked answer), but I would be happy to use fooList[42]->myMethod() as a compromise, seeing as -> CAN be overloaded (as opposed to . Which cannot).


However, I can't find any documentation for overloading operator->.


My best guess is that it must return a pointer to some object (say pObj), and C++ will invoke pObj->whatever.


Below is my attempted implementation. However, I'm running into a 'taking the address of a temporary object of type Object' warning.


I have, within my Object class:



const Object operator[] (const Object& key) const {
return Object{ PyObject_GetItem( p, key.p ) };
}


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
};


The idea is to allow myList[5]->someMemberObj = ... style syntax.


myList[5] resolves as a Proxy instance, which is wrapping an Object (the sixth element of myList). Let's call it myItem.


Now I want someProxy->fooFunc() or someProxy->fooProperty to invoke myItem.fooFunc() or myItem.fooProperty respectively.


I'm running into a 'taking the address of a temporary object of type Object' warning.


Aucun commentaire:

Enregistrer un commentaire