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

How to provide a non-const parameter to a custom sink backend?

本文关键字:const 参数 后端 自定义 接收器      更新时间:2023-10-16

接收后端不能在其构造函数中使用非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 &'
}

是否有任何方法提供一个自定义sink后端与非const对象引用,或者我做一些概念上的错误?

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或boost等效中。

    #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);