Как использовать оператор выходного потока, определенный в заголовке

Я хотел бы иметь возможность добавлять содержимое любого std::vector<T> в выходной поток. Я нашел этот код:

#ifndef DEBUG_H_
#define DEBUG_H_

#include <vector>

template < class T >
std::ostream& operator << (std::ostream& os, const std::vector<T>& v)
{
os << "[";
for (typename std::vector<T>::const_iterator ii = v.begin(); ii != v.end(); ++ii)
{
os << " " << *ii;
}
os << "]";
return os;
}#endif /* DEBUG_H_ */

и вставьте в заголовок Debug.h, Как я могу использовать этот оператор в моем проекте?

РЕДАКТИРОВАТЬ: я убедился, что это работает в модульном тесте:

#include "Debug.h"
TEST_F(AuxGTest, testVectorDebug) {
std::vector<int> vec(10, 42);
std::cout << "vec: " << vec << std::endl;
}

Но использование его с лог-операторами log4cxx не работает:

#include <log4cxx>
#include "Debug.h"
namespace Foo {
class Bar {
void foo() {
std::vector<int> vec(10, 42);
DEBUG("vec: " << vec);
}

}

}

Это приводит к следующему сообщению компилятора:

/usr/local/Cellar/log4cxx/0.10.0/include/log4cxx/helpers/messagebuffer.h:190:47: error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'

0

Решение

Где вы пытаетесь использовать это? Как заявлено, это в глобальном
пространство имен, поэтому оно не будет найдено ADL, если T это тип
определяется в глобальном пространстве имен. И это не будет найдено
нормальный поиск, если вы находитесь в пространстве имен, отличном от глобального
пространство имен, и есть operator<< в этом пространстве имен (которое
скрыл бы это). Это также не будет найдено, если вызвано в
шаблон, если какой-либо из аргументов является зависимым, так как
поиск зависимых имен использует только ADL.

И, конечно же, вы действительно не хотите делать это, кроме как в игрушке
программы. Различное использование std::vector потребуется
разные форматы вывода; гораздо лучше обернуть
std::vector в классе, и определить operator<< для
класс, для каждого различного семантического использования. (Для игрушечных программ вы
можно определить оператор в пространстве имен std, Неопределенное поведение,
но так как никто другой никогда не увидит код или
сохранить его, и это не конец света, если это не так
Работа…)

РЕДАКТИРОВАТЬ:

Так как кажется, что вы используете это для какой-то трассировки
или отладка: это один из случаев, когда имеет смысл
поддерживать единый выход для std::vector, поскольку он используется для
выход внутренний государство. С другой стороны, обычно в этом
чехол для ostream быть завернутым, что-то вроде:

class Logger
{
std::ostream* myDest;
public:
Logger( std::ostream* dest )
: myDest( dest )
{
}

template <typename T>
Logger& operator<<( T const& value )
{
if ( myDest != NULL ) {
*myDest << value;
}
return *this;
}
};

Это позволяет конфигурировать протоколирование во время выполнения (плюс автоматическое
вставка таких вещей, как __FILE__ а также __LINE__, если вы используете
макрос, чтобы получить экземпляр Logger); твой макрос DEBUG
может быть что-то вроде:

#define DEBUG getLogger( TRACELEVEL_DEBUG, __FILE__, __LINE__ )

где getLogger это глобальная функция, которая возвращает Logger
инициализируется с правильным ostream (или нулевой указатель, если
регистрация не активна для этого уровня). Как только вы это сделаете, вы можете
добавить специальные функции, такие как:

template <typename T>
Logger& Logger::operator<<( std::vector<T> const& value )
{
if ( myDest != NULL ) {
//  your code here...
}
return *this;
}

Поскольку одним из аргументов << оператор будет
экземпляр Logger, ADL найдет оператора, независимо.

3

Другие решения

Есть похожий вопрос о пользовательских операторах с log4cxx. я ответил этот вопрос, рекомендовав поместить оператора в log4cxx::helpers Пространство имен. Увидеть .

0

По вопросам рекламы [email protected]