One kind person in my past question about containers gave a description of the proxy class for interception rvalue mymap[100] == 200; . That is, 999 goes to the AVL tree, and then a file is created with the name 999 , and the value 100 is stored in it.

 template<typename T1, typename T2> struct PersistentMap; template<typename T1, typename T2> struct PersistentMapProxy { PersistentMap<T1, T2> & parent; T1 key; PersistentMapProxy(PersistentMap<T1, T2> & parent, T1 key) : parent(parent), key(key) {} const T2& operator = (const T2& value) const { parent.assign(key, value); return value; } operator const T2& () const { return parent.get(key); } }; template<typename T1, typename T2> struct PersistentMap { // ... typedef PersistentMapProxy<T1, T2> Proxy; Proxy operator[] (T1 key) { return Proxy(*this, key); } void assign(T1 key, const T2& value){ /*...*/ } // ... }; 

The proxy class works flawlessly with simple operations like:

 myMap[1] = 10; myMap[2] = 20; int c = 30; myMap[3] = c; 

But as soon as I complicate the assignment a bit, an error occurs.

Imagine that we have a method:

 void modify(int& a) {а += 5;} 

and I need to perform this action:

 modify(myMap[2]); 

that is, take and increase the value in the cell [2] by 5 points. In this case, errors occur:

1) (active) must be an lvalue

2) C2664 'void modify (int &)': cannot convert argument 1 from 'const lib :: PersistentMapProxy' to 'int &'

The modify method should be used and can not change it, which means you need to do something with the container and proxy class.

Could you tell me how to solve this problem? And it is desirable to give an example of a solution.

    2 answers 2

     template<typename T1, typename T2> struct PersistentMapProxy { PersistentMap<T1, T2> & parent; T1 key; T2 value; PersistentMapProxy(PersistentMap<T1, T2> & parent, T1 key) : parent(parent), key(key), value( parent.get(key) ) {} const T2& operator = (const T2& value_) const { value=value_; parent.assign(key, value); return value; } operator T2& () { return value; } ~PersistentMapProxy() { if(value!=parent.get(key)) parent.assign(key, value); } }; 

    But this approach is so mistaken that it is better not to show it at the interview.

    The correct way is to correct the modify function so that it takes the proxy as an argument.

      If you really need to provide the ability to call the type of modify(myMap[2]); , it is enough to implement the conversion operator of your proxy-type to a non-constant reference to the type (by analogy with the existing constant):

       operator T2&() { return parent.get(key); // тут должна быть соответствующая версия get }