Я пытаюсь реализовать свое собственное qDebug()
разработайте поток вывода отладки, это в основном, что я имею до сих пор:
struct debug
{
#if defined(DEBUG)
template<typename T>
std::ostream& operator<<(T const& a) const
{
std::cout << a;
return std::cout;
}
#else
template<typename T>
debug const& operator<<(T const&) const
{
return *this;
}
/* must handle manipulators (endl) separately:
* manipulators are functions that take a stream& as argument and return a
* stream&
*/
debug const& operator<<(std::ostream& (*manip)(std::ostream&)) const
{
// do nothing with the manipulator
return *this;
}
#endif
};
Типичное использование:
debug() << "stuff" << "more stuff" << std::endl;
Но я хотел бы не должным быть добавить станд.:: endl;
Мой вопрос в основном, как я могу сказать когда тип возврата operator<<
не будет используемым другим operator<<
(и тем самым добавьте endl
)?
Единственным путем я могу думать для достижения чего-либо как это, должен был бы создать список вещей распечатать со связанным с каждым временным объектом, созданным qDebug()
, затем для печати всего, наряду с запаздывающей новой строкой (и я мог сделать умные вещи как вставление пробелов) в ~debug()
, но очевидно это не идеально, так как у меня нет гарантии, что временный объект будет уничтоженным до конца объема (или я?).
Qt использует метод, аналогичный @evan. См. версию QDEBUG.H для деталей реализации, но они поток все в базовый текстовый поток, а затем промойте поток и конечную строку на разрушении временного объекта QDebug, возвращаемого QDEBUG () Отказ
Вставка потока ( <<
и извлечение ( >>
) должны быть не члены Отказ
Мой вопрос в основном, как я могу скажи, когда возвратный тип Оператор << не будет использоваться другой оператор << (и так подтверждает EndL)?
Вы не можете. Создайте функцию участника, чтобы специально добавить это или добавить ENDL
после того, как эти цепные звонки выполнены. Документе свой класс хорошо, чтобы клиенты знали, как его использовать. Это твоя лучшая ставка.
Что-то вроде этого сделает:
struct debug {
debug() {
}
~debug() {
std::cerr << m_SS.str() << std::endl;
}
public:
// accepts just about anything
template<class T>
debug &operator<<(const T &x) {
m_SS << x;
return *this;
}
private:
std::ostringstream m_SS;
};
, которое должно позволять вам делать такие вещи:
debug() << "hello world";
Я использовал табло, подобную этому в сочетании с блокировкой, чтобы обеспечить, как система регистрации журнала, которая может гарантировать, что записи журнала написано атомно.
Примечание : непроверенный код, но должен работать: -)
Когда вы пишете, что это типичное использование:
debug() << "stuff" << "more stuff" << std::endl;
Вы определенно планируете построить объект отладки каждый раз, когда вы его используете? Если это так, вы должны быть в состоянии получить поведение, которое вы хотите, имея делубюзор Destructor, добавьте новую строку:
~debug()
{
*this << std::endl;
... the rest of your destructor ...
}
, что означает, что вы не можете сделать что-то подобное:
// this won't output "line1" and "line2" on separate lines
debug d;
d << "line1";
d << "line2";