How to use an output stream operator defined in a header

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>&&'

Answers


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...)

EDIT:

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.


There is a similar question about user-defined operators with log4cxx. I answered that question by recommending placing the operator in the log4cxx::helpers namespace. See .


Need Your Help

Apache Cordova error uploading cropped image to server from IOS

ios angularjs cordova wcf visual-studio-cordova

On my IOS mobile application I am taking picture and then select a picture from gallery. After selecting this picture I am using ng-img-crop.js to crop this image and without saving this cropped im...

What transaction manager should I use for JBDC template When using JPA ?

java spring jpa jdbc

I am using standard JPA transaction manager for my JPA transactions. However, now I want to add some JDBC entities which will share the same 'datasource'. How can I make the JDBC operations transac...