Back to Arangodb

Technicalities

3rdParty/boost/1.78.0/libs/gil/doc/html/design/technicalities.html

3.12.9.12.3 KB
Original Source

Technicalities

Creating a reference proxy

Sometimes it is necessary to create a proxy class that represents a reference to a given object. Examples of these are GIL’s reference to a planar pixel (planar_pixel_reference) and GIL’s sub-byte channel references. Writing a reference proxy class can be tricky. One problem is that the proxy reference is constructed as a temporary object and returned by value upon dereferencing the iterator:

structrgb\_planar\_pixel\_iterator{typedefmy\_reference\_proxy\<T\>reference;referenceoperator\*()const{returnreference(red,green,blue);}};

The problem arises when an iterator is dereferenced directly into a function that takes a mutable pixel:

template\<typenamePixel\>// Models MutablePixelConceptvoidinvert\_pixel(Pixel&p);rgb\_planar\_pixel\_iteratormyIt;invert\_pixel(\*myIt);// compile error!

C++ does not allow for matching a temporary object against a non-constant reference. The solution is to:

  • Use const qualifier on all members of the reference proxy object:
template\<typenameT\>structmy\_reference\_proxy{constmy\_reference\_proxy&operator=(constmy\_reference\_proxy&p)const;constmy\_reference\_proxy\*operator-\>()const{returnthis;}...};
  • Use different classes to denote mutable and constant reference (maybe based on the constness of the template parameter)
  • Define the reference type of your iterator with const qualifier:
structiterator\_traits\<rgb\_planar\_pixel\_iterator\>{typedefconstmy\_reference\_proxy\<T\>reference;};

A second important issue is providing an overload for swap for your reference class. The default std::swap will not work correctly. You must use a real value type as the temporary. A further complication is that in some implementations of the STL the swap function is incorrectly called qualified, as std::swap. The only way for these STL algorithms to use your overload is if you define it in the std namespace:

namespacestd{template\<typenameT\>voidswap(my\_reference\_proxy\<T\>&x,my\_reference\_proxy\<T\>&y){my\_value\<T\>tmp=x;x=y;y=tmp;}}

Lastly, remember that constructors and copy-constructors of proxy references are always shallow and assignment operators are deep.

We are grateful to Dave Abrahams, Sean Parent and Alex Stepanov for suggesting the above solution.