очень нетривиальное объявление друга в шаблоне - PullRequest
2 голосов
/ 20 марта 2012
class Foo
{
    template <typename T> friend void T::persist(void);
    int test;
};

class Bar
{
    Foo foo;
    void persist(void) { foo.test = 42; } // fails
}

При этом я надеюсь, что метод-член persist () каждого класса, который его определяет, будет другом foo.Странная строка друга компилируется, но, похоже, ничего не делает.

Заранее спасибо.

1 Ответ

1 голос
/ 20 марта 2012

Вы не можете этого сделать. Вы не можете подружиться с членом всех типов, и ваша декларация template-friend неверна. Нет шаблона в:

class Foo
{
    template <typename T> 
    friend void T::persist(void);

    int test;
};

Обратите внимание, что объявление friend не является шаблоном. Вы можете подружиться с шаблонной функцией или классом, но в приведенном выше коде их нет.

Простой обходной путь - создание вспомогательного класса, из которого вы производите и предоставляющего метод доступа:

class Foo {
   friend class FooAccessor;
   int value;
};
class FooAccessor {
protected:
   void write( Foo& f, int value ) {
     f.value = value;
   }
};
class FooUser : private FooAccessor {
   Foo f;
   void persist() {
      write( f, 42 );
   }
};

Но вы, возможно, захотите вернуться к дизайну и поискать альтернативы, обратите внимание, что создание полей private и затем предоставление доступа каждому другому классу через декларацию friend не намного лучше, чем просто открытые поля. Если вы хотите объяснить, чего вы пытаетесь достичь, кто-то может вам помочь.

...