Search code examples
c++boostoperator-overloadingboost-logwidestring

Boost.Log ignores overloaded stream insertion operator


I have a class that I want to appear in log in a certain way, so I've overloaded its << operator:

class CWindowClassId
{
public:
    // ...
    friend std::wostream& operator<< (std::wostream& os, CWindowClassId const& classId);
}

Inserting the class above in log stream:

// ...
CWindowClassId classId(hWindow);
BOOST_LOG_TRIVIAL(debug) << "Window created, class = " << classId;

causes compilation error:

Error   1   error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const Sandbox::CWindowClassId' (or there is no acceptable conversion)    C:\local\boost_1_55_0\boost\log\utility\formatting_ostream.hpp  710

I know the error lies in the fact, that I've overloaded << for wide strings. All is fine when I use ostream instead of wostream, but I really want to use wide string version.

I've tried to set locale for a sink:

shared_ptr<log::sinks::synchronous_sink<log::sinks::text_file_backend> > sink = log::add_file_log("log.txt");
sink->imbue(boost::locale::generator()("en_US.UTF-8"));

And have BOOST_LOG_USE_WCHAR_T defined before any log-related includes.

Is there anything I can do to make logging work with wide string << operator?

I'm using Boost 1.55.0.


Solution

  • I don't think you can do this with BOOST_LOG_TRIVIAL. The trivial logger uses a underlying boost::sources::logger instead of boost::sources::wlogger, you can see that from trivial.hpp and trivial.cpp in the boost source file, and I can't see how we can change it unless we modify the source code. If you use a wlogger, it would work. Here is an example:

    #include <iostream>
    #include <string>
    #include <boost/log/sources/logger.hpp>
    #include <boost/log/common.hpp>
    
    namespace src = boost::log::sources;
    
    class CWindowClassId
    {
    public:
        // ...
        friend std::wostream& operator<< (std::wostream& os, CWindowClassId const& classId)
        {
            os << classId.ws;
            return os;
        }
    public:
        std::wstring ws;
    };
    
    int main(int argc, char* argv[])
    {
        src::wlogger lg;
        CWindowClassId id;
        id.ws = L"wide char";
        BOOST_LOG(lg) << "Hello, World! This is a wide character message."<<id;
        return 0;
    }