Я могу думать о четырех подходах.
Прежде всего, возьмите std::ostream
как ваш GeneralOutStream
, и предположите, что каждый наследует его. Может быть, напишите что-нибудь, что обертывает QTextStream
так, чтобы оно было std::ostream
.
Во-вторых, напишите template
метод, который принимает GeneralOutStream&& out
и работает на нем. Это требует раскрытия вашей реализации в вашем заголовке. Я бы порекомендовал это. Очень сильно, но это означает, что virtual
в конечном итоге становится бесполезным.
В-третьих, написать тип стирания GeneralOutStream
, что обнажает части общего из потока, который вы хотите, чтобы взаимодействовать с в своем классе с template
конструктор, который хранит переданному в родовом типа в pImpl
с virtual
методами, а затем использовать этот тип в рамках реализации вашего объекта. У этого есть накладные расходы времени исполнения и довольно сложно написать, и он напоминает шаблон std::function
- за исключением того, что GeneralOutStream
должен обрабатывать возможность писать целые множества типов!
Если бы я должен был написать # 3, GeneralOutStream
будет template
, который принимает последовательность Типов GeneralOutStream
предполагается обрабатывать, а затем делает некоторые метапрограммирования разоблачить именно те перегруженные к <<
. Это становится очень сложно, потому что вам нужно реплицировать разрешение перегрузки вручную.
Forth, создайте перечисление типов GeneralOutStream, которые вы хотите поддержать. Используйте методы двойной отправки, чтобы пересылать ссылки на экземпляры этих типов с помощью вызова метода virtual
, разделяя их с другой стороны и вызывая методы имплантации template
, требуя, чтобы класс реализации обрабатывал всю нумерацию. Это немного сложнее реализовать, чем # 3, ограничивает типы, которые вы можете передать методу draw
, но позволяет получить полный доступ к типу реализации class
.
Вы можете передать 'std :: ostream' ссылкой, если ваши объекты наследуются от него. Если нет, я бы пошел с шаблонами. Я также не добавлял бы эту зависимость, если бы ваши объекты не были потоками. –
Я бы пошел с шаблонами. Они только скомпилированы для определенного типа, только если этот тип используется где-то в вашем коде. Вы можете даже иметь специализированные версии для тех, кто не поддерживает оператор '<<'. Так что это лучшее решение IMO. –
Шаблон необходим, если вы хотите поддерживать * любой * поток, потому что потоки сами templatized. Мы - серьезные инженеры зрелой индустрии, у нас есть широкие персонажи и потоки для поддержки языков мира! и могут даже иногда их использовать, к нашему собственному изумлению ... –