Как перегрузить оператор ostream <<, чтобы заставить его работать с log4cxx в C ?

#c #operator-overloading #log4cxx

#c #оператор-перегрузка #log4cxx

Вопрос:

Допустим, у меня есть класс A и оператор<<, объявленный следующим образом:

 // A.h
class A
{
    // A stuff
};
std::ostreamamp; operator<<(std::ostreamamp; os, const Aamp; a);
  

где-то еще я использую свой регистратор с:

 LoggerPtr logger(LogManager::getLogger("ThisObject"));
A a;
LOG4CXX_INFO(logger, "A: " << a);
  

Компилятор жалуется:
двоичный файл ‘<<‘ : не найден оператор, который принимает правый операнд типа ‘const A’ (или нет приемлемого преобразования) D:devcpplibapache-log4cxxlog4cxxincludelog4cxxhelpersmessagebuffer.h 190

Эта ошибка приводит меня к объявлению operator<< :

 // messagebuffer.h
template<class V>
std::basic_ostream<char>amp; operator<<(CharMessageBufferamp; os, const Vamp; val) {
    return ((std::basic_ostream<char>amp;) os) << val;
}
  

LOG4XX_INFO макрос расширяется до:

 #define LOG4CXX_INFO(logger, message) { 
    if (logger->isInfoEnabled()) {
       ::log4cxx::helpers::MessageBuffer oss_; 
       logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
  

MessageBuffer также «определяет» этот оператор:

 // messagebuffer.h
template<class V>
std::ostreamamp; operator<<(MessageBufferamp; os, const Vamp; val) {
    return ((std::ostreamamp;) os) << val;
}
  

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

Комментарии:

1. @Alan Stokes: Я использую Visual Studio 2010

2. Попробуйте включить A.h перед messagebuffer.h

3. @Juraj Blaho: Как ты думаешь, почему это так? В то время, когда компилятор выполняет поиск, мой оператор идеально определен и известен.

4. @mister почему: Сообщение об ошибке предполагает, что оно неизвестно / не отображается.

5. @Juraj Blaho: Действительно, это так, но я думаю, это связано с тем фактом, что ошибка указывает на особенность, operator<< которая принимает a CharMessageBuffer вместо ostream . Я не хочу вводить зависимость реализации log4cxx в моем классе.

Ответ №1:

Вы могли бы попробовать объявить свой оператор << в пространстве имен std (это законно, поскольку вы передаете экземпляр вашего пользовательского типа):

 namespace std {
   ostreamamp; operator<<(ostreamamp; os, const Aamp; a);
}
  

Комментарии:

1. Я не привык искажать пространство имен, которое не мое, но я должен признать, что это сработало как шарм! Приветствия.

2. Мне интересно понять, почему компилятор не может найти мой оператор в этом контексте.

3. Я тоже! Я думаю, что ADL (поиск, зависящий от аргумента) должен заставить ваш код просто работать; но ADL полон тонкостей, и Visual Studio добавляет свои собственные особенности. Трюк с пространством имен std работал у меня раньше. Это не так плохо, как кажется, как только вы к этому привыкнете.

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

Ответ №2:

Предложение Алана поместить пользовательский оператор в std пространство имен работает. Но я предпочитаю помещать пользовательский оператор в log4cxx::helpers пространство имен, которое также работает. В частности,

 namespace log4cxx { namespace helpers {
    ostreamamp; operator<<(ostreamamp; os, const Aamp; a);
} }
  

Ответ №3:

У меня сейчас нет доступного компилятора, но я думаю, что проблема вызвана попыткой использовать оператор insert для постоянной строки. "A: " << a

Комментарии:

1. Я не вставляю постоянную строку; вы, должно быть, неправильно прочитали LOG4CXX_INFO расширение.