Nik Nik - 2 months ago 16
C++ Question

How to build log4cxx in Visual Studio 2015

I have been using log4cxx, it worked OK for my needs. We are moving to VS 2015 and I have discovered that the compiler in Visual Studio 2015 is throwing errors when I try to rebuild log4cxx 0.10.0.1. The build still works if I change the project toolset to Visual Studio 2013 (v120), but when I try to use it has problems at runtime.

See below the error message it occurs on multiple occasions .
Has anyone found a way to build log4cxx properly with Visual Studio 2015?

4>..\..\Log4cxx\log4cxx\apache-log4cxx-0.10.0\src\main\include\log4cxx/layout.h(90): error C2248: 'log4cxx::helpers::ObjectImpl::ObjectImpl': cannot access private member declared in class 'log4cxx::helpers::ObjectImpl'
4>..\..\Log4cxx\log4cxx\apache-log4cxx-0.10.0\src\main\include\log4cxx/helpers/objectimpl.h(43): note: see declaration of 'log4cxx::helpers::ObjectImpl::ObjectImpl'
4>..\..\SDKS\Log4cxx\log4cxx\apache-log4cxx-0.10.0\src\main\include\log4cxx/helpers/objectimpl.h(28): note: see declaration of 'log4cxx::helpers::ObjectImpl'
4>..\..\SDKS\Log4cxx\log4cxx\apache-log4cxx-0.10.0\src\main\include\log4cxx/layout.h(90): note: This diagnostic occurred in the compiler generated function 'log4cxx::Layout::Layout(const log4cxx::Layout &)'

Answer

I had the same problem and found a fix hopefully.

The problem is the definition of the base class ObjectImpl:

    class LOG4CXX_EXPORT ObjectImpl : public virtual Object
    {
    public:
        ObjectImpl();
        virtual ~ObjectImpl();
        void addRef() const;
        void releaseRef() const;

    protected:
        mutable unsigned int volatile ref;

    private:
        //
        //   prevent object copy and assignment
        //
        ObjectImpl(const ObjectImpl&);
        ObjectImpl& operator=(const ObjectImpl&);
    };

As you can see the class hides a copy constructor and the copy assignment operator, because the design using a reference counter has no suitable implementation. It would have been better to use shared pointers.

The new stl implementation uses the move semantic for their collection classes and when there is no copy constructor and copy assignment operator with move semantic it has to use the standard operators, which are not available.

To solve this problem, we have to add the move operators to the following classes: ObjectImpl, Layout, Filter, PatternConverter, TriggeringPolicy and RollingPolicyBase.

Here is my new implementation for ObjectImpl:

    class LOG4CXX_EXPORT ObjectImpl : public virtual Object
    {
    public:
        ObjectImpl();
        virtual ~ObjectImpl();
        void addRef() const;
        void releaseRef() const;

        // added for VS2015
        ObjectImpl(ObjectImpl && o)
        {
            ref = o.ref;
            o.ref = 0;
        }

        ObjectImpl& operator=(ObjectImpl && o)
        {
            ref = o.ref;
            o.ref = 0;

            return *this;
        }
        // -----

    protected:
        mutable unsigned int volatile ref;

    private:
        //
        //   prevent object copy and assignment
        //
        ObjectImpl(const ObjectImpl&);
        ObjectImpl& operator=(const ObjectImpl&);
    };

And one other example. The remaining classes are similar:

    class LOG4CXX_EXPORT Filter : public virtual OptionHandler,
        public virtual helpers::ObjectImpl
    {
        /**
        Points to the next filter in the filter chain.
        */
        FilterPtr next;
    public:
        Filter();

        // added for VS2015
        Filter(Filter && o)
            : helpers::ObjectImpl(std::move(o))
            , next( o.next )
        { }

        Filter& operator=(Filter && o)
        {
            helpers::ObjectImpl::operator=(std::move(o));
            next = o.next;
            return *this;
        }
        // end of added for VS2015

        ...

I hope that helps.