2013-07-12 3 views
1

Я интерфейс, который сводится кРазрешить оператор потока на производных классах

class interface 
{ 
    protected: 
     virtual void write(std::string const &) = 0; 
}; 

и производные классы, как

class derived : public interface 
{ 
    protected: 
     void write(std::string const & buf) 
     { 
      std::cout << buf << std::endl; 
     } 
}; 

В моем приложении эти объекты передаются вокруг, как смарт-указателей, т.е. std::shared_ptr<derived> , Я надеялся, что могу перегрузить оператор <<, но только для умных указателей производных от моего интерфейса. Я попытался это:

class interface 
{ 
    /* ... */ 
    private: 
     template <typename Derived> friend typename std::enable_if< 
      std::is_base_of<interface, Derived>::value, 
      std::shared_ptr<Derived> 
     >::type & operator<<(std::shared_ptr<Derived> & lhs, 
       std::string const & rhs) 
     { 
      lhs->write(rhs); 
      return lhs; 
     } 
}; 

Но когда я пытаюсь std::shared_ptr<derived> sp; sp << "test";, компилятор жалуется, что virtual void derived::write(const string&) is protected within this context (this context мой друг функция).

Есть ли способ достичь этого без избыточной записи оператора потока для каждого производного класса?

+0

Любая причина, по которой 'write' является' protected'? Из того, что вы опубликовали, у него есть только побочные эффекты, поэтому нет причин скрывать его от пользователя. В частности, поскольку пользователь в любом случае может наблюдать все эти побочные эффекты через вставку для вставки. – ComicSansMS

+0

Поскольку 'write' является виртуальным и в теле оператора' lhs' содержит 'Derived *', который можно конвертировать в 'interface *', вы можете «upcast» (а не ссылку «shared_ptr» напрямую, а основной указатель): http : //ideone.com/lqZ2o8 (но, как сказано @ user2362671, вы можете использовать 'std :: shared_ptr sp (new производный)' вместо) –

+0

@ComicSansMS Я хотел, чтобы публичный API был как можно более чистым, и решение gx_ кажется разрешить мне это, или есть ли недостаток этого решения, которого я не вижу? – user2573221

ответ

0

Почему бы не просто определить ваш оператор как:

friend std::shared_ptr<interface> &operator<<(std::shared_ptr<interface> & lhs, std::string const & rhs); 

и передать свои объекты как std::shared_ptr<interface>?

+0

Я думал об этом, но существующая кодовая база ограничивает меня предоставлением обоих вариантов. – user2573221

+0

@ user2573221 Почему? Существуют ли функции 'производные', которые вы должны вызывать, которые не объявлены виртуальными в' base'? –

+0

Есть функции в 'производных', которые вообще не объявляются в' base' – user2573221

Смежные вопросы