如何为自定义接收器后端提供非const参数?

时间:2014-08-21 10:10:16

标签: c++ boost-log

不能使用在其构造函数中期望非const参数的接收器后端,因为包装接收器前端似乎只转发const参数。

示例:

class buffering_sink_backend :
    public boost::log::sinks::basic_formatted_sink_backend <
    char,
    boost::log::sinks::synchronized_feeding
    >
{
public:
    buffering_sink_backend(std::string &buffer)
        : _buffer(buffer)
    {}

    void consume(boost::log::record_view const &rec, string_type const &formattedMessage)
    {
        _buffer += formattedMessage;
    }

private:
    std::string &_buffer;
};

typedef boost::log::sinks::synchronous_sink< buffering_sink_backend > buffering_sink;


void main()
{
    std::string buffer;

    buffering_sink *bla = new buffering_sink(buffer);   // --> compiler error: cannot convert argument 1 from 'const std::string' to 'std::string &'
}

有没有办法提供带有非const对象引用的自定义接收器后端,或者我在概念上做错了什么?

1 个答案:

答案 0 :(得分:0)

synchronous_sink实际上并不使用C ++ 11可变参数模板和完美转发,而是使用一些预处理器魔术来生成一系列带有const引用的转发构造函数,以便在宏扩展后它变为

template< typename T0 > 
explicit synchronous_sink( T0 const& arg0) 
         : base_type(false),
           m_pBackend(boost::make_shared< sink_backend_type >( arg0)) {}

/* ... 13 constructors omitted ... */

template< typename T0 , typename T1 , typename T2 , typename T3 , typename T4 ,
          typename T5 , typename T6 , typename T7 , typename T8 , typename T9 ,
          typename T10 , typename T11 , typename T12 , typename T13 , typename T14 > 
explicit synchronous_sink( T0 const& arg0 , T1 const& arg1 , T2 const& arg2 , 
                           T3 const& arg3 , T4 const& arg4 , T5 const& arg5 , 
                           T6 const& arg6 , T7 const& arg7 , T8 const& arg8 ,
                           T9 const& arg9 , T10 const& arg10 , T11 const& arg11 ,
                           T12 const& arg12 , T13 const& arg13 , T14 const& arg14) 
         : base_type(false),
           m_pBackend(boost::make_shared< sink_backend_type >( 
                            arg0 , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 ,
                            arg8 , arg9 , arg10 , arg11 , arg12 , arg13 , arg14)) {}

因此,如果将buffer直接传递给此构造函数,它将始终通过const引用传递。

可能的解决方案是:

  • 将非const引用包含在std::reference_wrapper或等效提升中。

    #include <functional>  // for std::ref (C++11 only)
                           // or #include <boost/ref.hpp> for boost::ref
    
    buffering_sink *bla = new buffering_sink(std::ref(buffer)); // or boost::ref(buffer)
    
  • 自己制作后端,然后使用explicit synchronous_sink(shared_ptr< sink_backend_type > const& backend);构造函数:

    boost::shared_ptr<buffering_sink_backend> backend = boost::make_shared<buffering_sink_backend>(buffer);
    buffering_sink *bla = new buffering_sink(backend);