Как создать тег типа для специализации шаблона

У меня есть собственный класс ведения журнала, который поддерживает синтаксис iostream через шаблонный оператор << :

template< class T >
MyLoggingClass & operator <<(MyLoggingClass &, const T &) {
    // do stuff
}

У меня также есть специализированная версия этого оператора, которая должна вызываться при завершении сообщения журнала:

template< >
MyLoggingClass & operator <<(MyLoggingClass &, consts EndOfMessageType &){
    // build the message and process it
}

EndOfMessageType определяется следующим образом:

class EndOfMessageType {};
const EndOfMessageType eom = EndOfMessageType( );

Глобальная константа eom определяется так, чтобы пользователи могли использовать его так же, как std :: endl в конце своих сообщений журнала. У меня вопрос, есть ли какие-либо подводные камни в этом решении или есть какой-то определенный шаблон для этого?

Заранее спасибо!

1
задан Björn Pollex 25 August 2010 в 14:04
поделиться

3 ответа

Я думаю, ваше решение приемлемо. Если вы хотите сделать это по-другому, вы можете создать класс Message, который будет использоваться вместо вашего MyLoggingClass и обеспечивать автоматическое завершение.

{
  Message m;
  m << "Line: " << l; // or m << line(l) 
  m << "Message: foo"; // or m << message("foo");
  log << m; // this would automatically format the message
}
0
ответ дан 2 September 2019 в 21:51
поделиться

Я сделал это так, как и некоторые другие люди. Есть функция Ошибка / Журнал / Предупреждение / и т. д., которая может выглядеть так

DiagnosticBuilder Error( ErrType type, string msg, int line );

Это вернет временный объект построителя, класс которого в основном определен как

struct DiagnosticBuilder {
  DiagnosticBuilder(std::string const& format)
    :m_emit(true), m_format(format) 
  { }
  DiagnosticBuilder(DiagnosticBuilder const& other) 
    :m_emit(other.m_emit), m_format(other.m_format), m_args(other.m_args) {
    other.m_emit = false;
  }
  ~DiagnosticBuilder() {
    if(m_emit) {
      /* iterate over m_format, and print the next arg 
         everytime you hit '%' */
    }
  }

  DiagnosticBuilder &operator<<(string const& s) {
    m_args.push_back(s);
    return *this;
  }
  DiagnosticBuilder &operator<<(int n) {
    std::ostringstream oss; oss << n;
    m_args.push_back(oss.str());
    return *this;
  }
  // ...
private:
  mutable bool m_emit;
  std::string m_format;
  std::vector<std::string> m_args;
};

Так что, если вы строите сообщение журнала в цикле, пусть так и будет

DiagnosticBuilder b(Error("The data is: %"));
/* do some loop */
b << result;

Как только автоматически вызывается деструктор компоновщика, сообщение генерируется. В основном вы использовали бы его анонимно

Error("Hello %, my name is %") << "dear" << "litb";
0
ответ дан 2 September 2019 в 21:51
поделиться

std::endl — это функция, а не объект, а operator<< перегружен для приема указателя на функцию, принимающую и возвращающую ссылку на ostream. . Эта перегрузка просто вызывает функцию и передает *this.

#include <iostream>

int main()
{
    std::cout << "Let's end this line now";
    std::endl(std::cout); //this is the result of cout << endl, or cout << &endl ;) 
}

Просто альтернатива для рассмотрения.

Кстати, я не думаю, что есть необходимость в специализации оператора: обычная перегрузка делает то же самое, если не лучше.

2
ответ дан 2 September 2019 в 21:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: