Search code examples
c++boostboost-log

boost::log::record_view assignment operator


#include <boost/log/core/record_view.hpp>

struct A
{
   boost::log::record_view view;
};

int main()
{
   const A a = {};
   A b;
   b = a;

   const boost::log::record_view r;
   boost::log::record_view rr;
   rr = r;
}

The second is compiled, while first is not. The compiler says, implicit copy-assignment operator is in form A& A::operator=(A&), but I have no idea why the second is compiled in this case. I can of course write manually overloaded operator =, but I want to know the cause of this behavior.

Live example

It looks like the problem is only with C++98, so only with move emulation in boost.

BOOST_COPYABLE_AND_MOVABLE(record_view)

where

   #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
      public:\
      TYPE& operator=(TYPE &t)\
      {  this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\

Solution

  • Maybe this will help someone, problem is, that actually record_view has 3 assignment operators. One is from BOOST_COPYABLE_AND_MOVABLE in the form

    TYPE& operator=(TYPE &t)\
          {  this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\
    

    And the other two are:

    /*!
     * Copy assignment
     */
    record_view& operator= (BOOST_COPY_ASSIGN_REF(record_view) that) BOOST_NOEXCEPT
    {
        m_impl = that.m_impl;
        return *this;
    }
    
    /*!
     * Move assignment. Source record contents unspecified after the operation.
     */
    record_view& operator= (BOOST_RV_REF(record_view) that) BOOST_NOEXCEPT
    {
        m_impl.swap(that.m_impl);
        return *this;
    }
    

    The second code compiled due to the second operator, where BOOST_COPY_ASSIGN_REF is

       #define BOOST_COPY_ASSIGN_REF(TYPE)\
          const ::boost::rv< TYPE >& \
    

    But the compiler will generate operator = in the form const T& only if

    N4296 12.8/18.2

    for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy assignment operator whose parameter is of type const M&, const volatile M& or M.

    So, only the first assignment operator of record_view will be checked.