1

I recently stumbled up this proxy class for making c++ primitive members "read only" (publicly act as const references, but privately non const). This potentially eliminates the need for boilerplate "getters". The proxy class looks like:

template <Container,Primitive>
class RO
{
  friend Container;
public:
                           inline operator Primitive() const             { return x; } 
  template<typename Other> inline bool  operator==(const Other& y) const { return x == y; }       
  template<typename Other> inline bool  operator!=(const Other& y) const { return x != y; }       
  template<typename Other> inline bool  operator< (const Other& y) const { return x < y; }        
  template<typename Other> inline bool  operator> (const Other& y) const { return x > y; }        
  template<typename Other> inline bool  operator<=(const Other& y) const { return x <= y; }       
  template<typename Other> inline bool  operator>=(const Other& y) const { return x >= y; }       
  template<typename Other> inline Other operator+ (const Other& y) const { return x + y; }        
  template<typename Other> inline Other operator- (const Other& y) const { return x - y; }
  ... // all other const operator overloads
protected:       
                           inline RO()                                  :x(){ }
  template<typename Other> inline RO(const Other& y)                    :x(y) { }
  template<typename Other> inline Primitive& operator= (const Other& y) { return x = y; }
  template<typename Other> inline Primitive& operator+=(const Other& y) { return x += y; }
  template<typename Other> inline Primitive& operator-=(const Other& y) { return x -= y; }
  template<typename Other> inline Primitive& operator*=(const Other& y) { return x *= y; }
  template<typename Other> inline Primitive& operator/=(const Other& y) { return x /= y; }
  ... // all other non-const operator overloads
                           inline Primitive* ptr()                      { return &x; }
                           inline Primitive& ref()                      { return x; }
                           inline const Primitive* const_ptr() const    { return &x; }
                           inline const Primitive& const_ref() const    { return x; }
  Primitive x;
};

This seems to work as desired if I have a flat class structure: just some class A which has RO proxy's for its read-only members. But as soon as I have some derived class B : public A, then I get into trouble. I'd like to have B read and write to the read-only RO members of defined in the inherited class A. But seeing as friendship is non-inherited. I'm not sure how to go about this. Same applies to direct friends of A: friendship is non-transitive.

Is there a construction of "read-only" proxies which are writable to friends and derived classes?

Community
  • 1
  • 1
Alec Jacobson
  • 6,032
  • 5
  • 51
  • 88
  • 4
    You wanted to eliminate boilerplate, and you would up with *that*? Yikes. :) – John Zwinck Oct 15 '14 at 12:54
  • 3
    I stopped worrying about all that C++ "thwart the evil maintainer" stuff the day I read the linux kernel 0.01 – Adrian May Oct 15 '14 at 13:00
  • Is there any reason not to use a getter (as shown in the other answers too)? – edmz Oct 15 '14 at 15:40
  • 2
    @John Zwinck, How is this boilerplate even comparable to getters? This class is defined once in a reusable header, and then I only need to add a few characters around each new member function. – Alec Jacobson Oct 15 '14 at 18:44
  • 2
    @black, getters are a tedious hassle to keep writing and make code calling them less readable. When quickly prototyping it's too easy to opt for the lazy route of declaring everything `public`. See the motivation behind Ruby's `attr_reader` for more. – Alec Jacobson Oct 15 '14 at 18:47

0 Answers0