Я интерфейс, который сводится кРазрешить оператор потока на производных классах
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
мой друг функция).
Есть ли способ достичь этого без избыточной записи оператора потока для каждого производного класса?
Любая причина, по которой 'write' является' protected'? Из того, что вы опубликовали, у него есть только побочные эффекты, поэтому нет причин скрывать его от пользователя. В частности, поскольку пользователь в любом случае может наблюдать все эти побочные эффекты через вставку для вставки. – ComicSansMS
Поскольку 'write' является виртуальным и в теле оператора' lhs' содержит 'Derived *', который можно конвертировать в 'interface *', вы можете «upcast» (а не ссылку «shared_ptr» напрямую, а основной указатель): http : //ideone.com/lqZ2o8 (но, как сказано @ user2362671, вы можете использовать 'std :: shared_ptr sp (new производный)' вместо) –
@ComicSansMS Я хотел, чтобы публичный API был как можно более чистым, и решение gx_ кажется разрешить мне это, или есть ли недостаток этого решения, которого я не вижу? – user2573221