Защищенный прокси-класс только для чтения для примитивов в С++

Недавно я наткнулся на этот прокси-класс для создания примитивных членов С++ "только для чтения" (публично действуют как константные ссылки, но в частном порядке не константа). Это потенциально устраняет необходимость в шаблонных «геттерах». Прокси-класс выглядит так:

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

Кажется, это работает так, как хотелось бы, если у меня есть плоская структура класса: просто некоторый class A, который имеет RO прокси для своих членов только для чтения. Но как только у меня есть какие-то производные class B : public A, то у меня возникают проблемы. Я хочу, чтобы B читались и записывались в доступные только для чтения RO члены, определенные в унаследованном классе A. Но видеть, как дружба не передается по наследству. Я не уверен, как это сделать. То же самое относится и к прямым друзьям A: дружба нетранзитивна.

Существует ли конструкция прокси-серверов «только для чтения», которые доступны для записи друзьям и производным классам?


person Alec Jacobson    schedule 15.10.2014    source источник
comment
Вы хотели избавиться от шаблонного кода и согласились бы с этим? Угу. :)   -  person John Zwinck    schedule 15.10.2014
comment
Я перестал беспокоиться обо всем, что C++ мешает злым мейнтейнерам, в тот день, когда я прочитал ядро ​​Linux 0.01.   -  person Adrian May    schedule 15.10.2014
comment
Есть ли причина не использовать геттер (как показано и в других ответах)?   -  person edmz    schedule 15.10.2014
comment
@John Zwinck, как этот шаблон вообще сравним с геттерами? Этот класс определяется один раз в многократно используемом заголовке, а затем мне нужно всего лишь добавить несколько символов вокруг каждой новой функции-члена.   -  person Alec Jacobson    schedule 15.10.2014
comment
@black, геттеры - утомительные хлопоты, чтобы продолжать писать и делать код, вызывающий их, менее читаемым. При быстром прототипировании слишком легко выбрать ленивый путь объявления всего public. Узнайте больше о мотивах attr_reader Ruby.   -  person Alec Jacobson    schedule 15.10.2014