2013-06-17 6 views
2

Мне нужно нарисовать мой объект на выходе, который обычно равен cout. Но я также хочу, чтобы пользователь мог вводить любой поток, в котором есть оператор << (такой как QTextStream), поэтому он не обязательно должен быть cout каждый раз. Какой самый простой способ определить такой параметр?Параметр типа «имеет« оператор »

Так это то, что я хотел бы иметь, что-то компилируется Тхо: (. Что я делаю атм)

virtual void draw(GeneralOutStream out = std::cout) 
{ 
    out << m_name << std::endl; 
} 

Я знаю, что я мог бы использовать шаблоны, , но я надеялся, было бы решение, которое не требует шаблонов. Тем не менее, решение шаблона отлично работает, поэтому в принципе мне просто интересно.

+1

Вы можете передать 'std :: ostream' ссылкой, если ваши объекты наследуются от него. Если нет, я бы пошел с шаблонами. Я также не добавлял бы эту зависимость, если бы ваши объекты не были потоками. –

+0

Я бы пошел с шаблонами. Они только скомпилированы для определенного типа, только если этот тип используется где-то в вашем коде. Вы можете даже иметь специализированные версии для тех, кто не поддерживает оператор '<<'. Так что это лучшее решение IMO. –

+0

Шаблон необходим, если вы хотите поддерживать * любой * поток, потому что потоки сами templatized. Мы - серьезные инженеры зрелой индустрии, у нас есть широкие персонажи и потоки для поддержки языков мира! и могут даже иногда их использовать, к нашему собственному изумлению ... –

ответ

2

Я могу думать о четырех подходах.

Прежде всего, возьмите 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.

+0

Мне нужно немного поиграть с ними, но я думаю, что я просто зайду со вторым решением ..: P Спасибо –

0

Вы хотите решение любого потока (полученный из std::ostream) или для любого объекта, который имеет << оператор?

В первом случае, вы можете передать ссылку на объект потока:

virtual void draw(std::ostream& out = cout) { 
    out << m_name << std::endl; 
} 

Passing копию не будет компилировать.

Во втором случае основной проблемой является интерфейс, поскольку, по-видимому, вы хотите определить эту функцию как виртуальный элемент. Если это не так, и вы все еще хотите получить решение для любого объекта (необязательный стандарт ostream, но любой с оператором <<), вам придется использовать шаблоны.

+0

'std :: ostream' отлично работает без какого-либо виртуального оператора' << '... –

+0

@ nm: Я знаю это. Когда я сказал «вам придется использовать шаблоны», я имел в виду второй случай: любой объект, поддерживающий оператор '<<' и, конечно, без виртуального требования. Я отредактировал ответ, чтобы он стал яснее. (Дайте мне знать, если еще не ясно смысл моего ответа). – Gonmator

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