I would like to be able to append the content of any std::vector<T>
to an output stream. I've found this code:
#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_ */
and put in in a header Debug.h
. How can I use this operator troughout my project?
EDIT: I have verified that this works in a unit test:
#include "Debug.h"
TEST_F(AuxGTest, testVectorDebug) {
std::vector<int> vec(10, 42);
std::cout << "vec: " << vec << std::endl;
}
But using it with log statements of log4cxx does not work:
#include <log4cxx>
#include "Debug.h"
namespace Foo {
class Bar {
void foo() {
std::vector<int> vec(10, 42);
DEBUG("vec: " << vec);
}
}
}
This results in the following compiler message:
/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>&&'
Where are you trying to use it? As declared, it's in the global
namespace, so it won't be found by ADL unless T
is a type
defined in the global namespace. And it won't be found by
normal lookup if you're in a namespace other than global
namespace, and there is an operator<<
in that namespace (which
would hide it). It also won't be found if invoked in
a template, if any of the arguments are dependent, since
dependent name lookup only uses ADL.
And of course, you really don't want to do this except in toy
programs. Different uses of std::vector
will require
different output formats; it's far better to wrap the
std::vector
in a class, and define the operator<<
for the
class, for each different semantic use. (For toy programs, you
can define the operator in namespace std
. Undefined behavior,
but since no one else will ever see the code, or have to
maintain it, and it's not the end of the world if it doesn't
work...)
Since it seems that you're using this for some sort of tracing
or debugging: this is one case where it does make sense to
support a unified output for std::vector
, since it is used to
output internal state. On the other hand, it is usual in this
case for the ostream
to be wrapped, something like:
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;
}
};
This allows runtime configuration of the logging (plus automatic
insertion of things like __FILE__
and __LINE__
, if you use
a macro to get the instance of Logger
); your macro DEBUG
might be something like:
#define DEBUG getLogger( TRACELEVEL_DEBUG, __FILE__, __LINE__ )
where getLogger
is a global function which returns a Logger
initialized with the correct ostream
(or a null pointer, if
logging isn't active for that level). Once you do this, you can
add special functions, like:
template <typename T>
Logger& Logger::operator<<( std::vector<T> const& value )
{
if ( myDest != NULL ) {
// your code here...
}
return *this;
}
Since one of the arguments the the <<
operator will be an
instance of Logger
, ADL will find the operator, regardless.