I've finally got a working Proxy pattern. The original task is presented here. My test case is on coliru.It appears to flow through the correct pathways, however I am grateful for feedback and possible improvements.EDIT: I've reworked the code to provide sensible trace output, so it is possible to examine the flow under various situations. I'm not sure I've caught every possible situation though.EDIT: I think I've now trapped all possible scenarios. Complex cases like (a[u] = b[v]) = foo degenerate into a sequence of steps. And I've isolated all the possible steps. The only thing I still need to work out is whether there is any possibility of invalid pointers causing trouble. In the original code every PyObject* is wrapped in an Object, and the Object's destructor takes care of decrementing the reference count. In order to simplify the proxy logic, I'm using bare pointers -- otherwise the complexity is just horrific, with const considerations creeping in. So I need to make sure this doesn't introduce any danger.  Finally, I'm moving away from the idea of using ->. mainly because I'm realising that if ob[idx] is to behave like an object, the proxy class must contain all the initialisers and converters and methods that object contains. -> provides a way of avoiding duplicating the methods, but there is no way to avoid duplicating the initialisers and converters. Hence introducing a new syntax to solve one third of the problems is a bad plan. Especially when that syntax is a compromise in the first place. It should be ob[idx].foo not ->foo.#include <iostream>#include <string>#include <vector>#include <memory>using namespace std;using PyObject = string;// Dummies for Python C-API functionsvoid      PyObject_SetItem( PyObject* pyob, PyObject* key, PyObject* value ) {     cout << PyObject_SetItem                            << *pyob << [ << *key << ]= << *value << endl; }PyObject* PyObject_GetItem( PyObject* pyob, PyObject* key )                  {     cout << PyObject_GetItem                            << *pyob << [ << *key << ]            << endl;    return new string( item@ + *pyob + [ + *key + ] ); }class Object {public:    PyObject* p;    Object() {};    Object(PyObject* _p) : p{_p} { cout << Object{  << (p==nullptr?0:*p) <<  } << endl; }    void someMethod() { cout << Object::someMethod() << endl; }    PyObject* ptr() { return p; }    Object& operator= (const Object& rhs) {        cout << const Object& operator=  << endl;        p = rhs.p;        return *this;    }    class Proxy {    private:        PyObject* container;        PyObject* key;    public:        // at this moment we don't know whether it is 'c[k] = x' or 'x = c[k]'        Proxy( PyObject* c, PyObject* k ) : container{c}, key{k} {             cout << Proxy( << *c << ,  << *k << ) << endl;         }        ~Proxy(){ cout << ~Proxy() << endl; }        // Rvalue        // e.g. fooObject = myList[5]        operator Object() const {            cout << Proxy::operator Object() const             R-VALUE ACCESS << endl;             return { PyObject_GetItem(container,key) };        }        // Lvalue        // e.g. (something = ) myList[5] = foo        Proxy&  operator= (const Object& rhs_ob) {            cout << Proxy& Proxy::operator= (const Object&)    L-VALUE ACCESS << endl;             PyObject_SetItem( container, key, rhs_ob.p );             return *this; // allow daisy-chaining a = b = c etc        }        /*         This is to handle ... = ob[a] = ob[b] = ... .           The compiler provides an automatic 'Proxy operator=', unless I provide one.          My first idea is to eliminate this 'Proxy operator=', and hope that when the compiler encounters          'fooProxy=barProxy' it's overload resolution will notice Proxy provides conversion to Object,          and produce 'fooProxy=Object(barProxy)'.         Unfortunately, the deleted function still participates in overload resolution. (Why??)         And consequently the compiler produces a 'Proxy operator=' error instead.         */        Proxy&  operator= (const Proxy& rhs) {            cout << Proxy& Proxy::operator= (const Proxy&)     PROXY-PROXY << endl;             cout << getting rhs...  << endl;            PyObject* val = rhs->ptr();            cout << ... =  << *val << endl;            PyObject_SetItem( container, key, val );                        return *this; // allow daisy-chaining a = b = c etc        }        Object operator->() const {             cout << Object Proxy::operator->() << endl;             return { PyObject_GetItem(container,key) };         }    };    /*      This overload is unnecessary, and is just for efficiency.      If ob is const, we know that we won't be doing ob[idx]=...     And so we can bypass having to engage the proxy mechanism.    */    const Object  operator[] (const Object& key)  const {         cout << const Object Object::operator[]            setting  << *p << [ << *(key.p) << ] CONST-SHORTCUT << endl;         return { PyObject_GetItem( p, key.p ) };     }    Proxy operator[] (const Object& key) {        cout << Proxy Object::operator[]                   creating proxy obj for  << *p << [ << *(key.p) << ] << endl;         return { p, key.p };    }    const Object* operator -> () const {         cout << const Object* Object::operator ->  << endl;         return this;     }    Object* operator -> () {         cout << Object* Object::operator -> << endl;         return this;     }        };int main(){    PyObject a=ob,b=idx,c=targ;    Object ob=Object(&a), idx=Object(&b), targ=Object(&c);    Object result;    // std::endl flushes    #define DO(x) cout << - - - - - - - - - - - - - - - - \n EXECUTING:  #x << endl; x;    DO(         PyObject pyob_in_const_ob = pyob_in_const_ob;        const Object const_ob(&pyob_in_const_ob);         //const_ob[idx] = targ; <-- can't assign to const obviously!        result = const_ob[idx];         )    DO( Object out = ob[idx]; )    DO( ob[idx] = targ )    DO( auto x = ob[idx] )    DO(         PyObject d=idy;        Object idy=Object(&d);        ob[idx] = ob[idy];         )    DO( ob[idx] = ob[idy] = targ )    ob[idx]->someMethod();    DO( PyObject* w = ob[idx]->p; );    DO( /* avoid variable not used warnings */ )    cout << w;    cout << &out;} 
Proxy pattern for supporting '... = ob[idx]->someObjMember = ...' type access
c++;c++11;proxy