【问题标题】:Clarification on the use of `boost::bind` and `this`关于使用 `boost::bind` 和 `this` 的说明
【发布时间】:2015-02-20 05:37:33
【问题描述】:

我今天对 boost::asio 项目进行了一些修改,在尝试将绑定函数传递给异步调用时遇到了令人困惑的编译错误。

我花了几个小时摆弄这段代码,所以我怀疑我错过了一些愚蠢的东西。谁能指出我哪里出错了,我将不胜感激。

error: no match for call to ‘(boost::_mfi::mf3<void, ClientServerManager, 
    const MCServer&, boost::shared_ptr<Connection>, 
    const boost::system::error_code&>) (ClientServerManager*&, 
    MCServer&, boost::shared_ptr<Connection>&, 
    const MCServer&)’

注意到const MCServer&amp; 出现了两次?我的绑定语句不是这样写的:

void ClientServerManager::onConnect(const MCServer& server_info, 
    boost::shared_ptr<Connection> con,
    const boost::system::error_code& err,
    tcp::resolver::iterator i) {

    // Instruct utility to do some work, and call our function when complete.
    con->statusPing(
        boost::bind( // <-- OFFENDING CODE
            &ClientServerManager::onPingCompletion,
            this,
            server_info,
            con,  // shared_ptr to connection (maintains scope)
            boost::asio::placeholders::error // in case of a downstream failure
        )
    );
}

在Connection header中statusPing(...)定义如下:

void statusPing(boost::function<
    void(
        MCServer&, boost::shared_ptr<Connection>, 
        const boost::system::error_code&
    )>);

最终要调用的处理程序:

void ClientServerManager::onPingCompletion(
    const MCServer& server_info, 
    boost::shared_ptr<Connection>,     
    const boost::system::error_code& err){
    // Use the results to drive some function...
}

背景:

  • 我有一个类遍历服务器列表并打开 与他们建立短暂的联系,以确保他们正在运作 适当地。
  • 该类使用一个实用程序,Connection,它继承 boost::enable_shared_from_this. 因此,我调用一个函数Connection::create(..) 来获取boost::shared_ptr 开始工作。当进行任何异步调用时,必须传递此指针以将连接保持在范围内。
  • 在这种情况下,成功建立连接后,我想将执行传递给Connection,以便它可以执行一些任务,并且我希望它在这些任务完成后调用句柄。 在这种情况下,我无法让 boost::bind 正确编译。
  • 现在我遇到的问题是boost::bind 可能与boost::asio::placeholders::error 模板的使用有关。

完整输出如下:

   g++ -std=c++0x -DBOOST_LOG_DYN_LINK -I/home/donald/Desktop/workspace/MCProxy/Debug/ -O3 -march=corei7-avx -g1 -w -c -fmessage-length=0 -MMD -MP -MF"src/ClientServerManager.d" -MT"src/ClientServerManager.d" -o "src/ClientServerManager.o" "../src/ClientServerManager.cpp"
In file included from ....
/boost/bind/bind.hpp: In instantiation of ‘void boost::_bi::list4<A1, A2, A3, A4>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>; A = boost::_bi::list3<const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>; A1 = boost::_bi::value<ClientServerManager*>; A2 = boost::_bi::value<MCServer>; A3 = boost::_bi::value<boost::shared_ptr<Connection> >; A4 = boost::arg<1> (*)()]’:
/boost/bind/bind_template.hpp:116:59:   required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&, A2&, A3&) [with A1 = const MCServer; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code; R = void; F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>; L = boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()>; boost::_bi::bind_t<R, F, L>::result_type = void]’
/boost/function/function_template.hpp:153:11:   required from ‘static void boost::detail::function::void_function_obj_invoker3<FunctionObj, R, T0, T1, T2>::invoke(boost::detail::function::function_buffer&, T0, T1, T2) [with FunctionObj = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&]’
/boost/function/function_template.hpp:934:60:   required from ‘void boost::function3<R, T1, T2, T3>::assign_to(Functor) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&]’
/boost/function/function_template.hpp:722:7:   required from ‘boost::function3<R, T1, T2, T3>::function3(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/boost/function/function_template.hpp:1071:16:   required from ‘boost::function<R(T0, T1, T2)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; T0 = const MCServer&; T1 = boost::shared_ptr<Connection>; T2 = const boost::system::error_code&; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
../src/ClientServerManager.cpp:90:3:   required from here
/boost/bind/bind.hpp:457:9: error: no match for call to ‘(boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>, const boost::system::error_code&>) (ClientServerManager*&, MCServer&, boost::shared_ptr<Connection>&, const MCServer&)’
In file included ....
/boost/bind/mem_fn_template.hpp:366:85: note: candidates are:
/boost/bind/mem_fn_template.hpp:391:7: note: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T*, A1, A2, A3) const [with R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:391:7: note:   no known conversion for argument 4 from ‘const MCServer’ to ‘const boost::system::error_code&’
/boost/bind/mem_fn_template.hpp:396:25: note: template<class U> R boost::_mfi::mf3::operator()(U&, A1, A2, A3) const [with U = U; R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:396:25: note:   template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note:   cannot convert ‘(& a)->boost::_bi::list3<A1, A2, A3>::operator[]<const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>(boost::_bi::storage4<A1, A2, A3, boost::arg<I> (*)()>::a4_<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, 1>)’ (type ‘const MCServer’) to type ‘const boost::system::error_code&’
In file included ....
/boost/bind/mem_fn_template.hpp:404:25: note: template<class U> R boost::_mfi::mf3::operator()(const U&, A1, A2, A3) const [with U = U; R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:404:25: note:   template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note:   cannot convert ‘(& a)->boost::_bi::list3<A1, A2, A3>::operator[]<const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>(boost::_bi::storage4<A1, A2, A3, boost::arg<I> (*)()>::a4_<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, 1>)’ (type ‘const MCServer’) to type ‘const boost::system::error_code&’
In file included from ....
/boost/bind/mem_fn_template.hpp:412:7: note: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T&, A1, A2, A3) const [with R = void; T = ClientServerManager; A1 = const MCServer&; A2 = boost::shared_ptr<Connection>; A3 = const boost::system::error_code&]
/boost/bind/mem_fn_template.hpp:412:7: note:   no known conversion for argument 1 from ‘ClientServerManager*’ to ‘ClientServerManager&’

编辑:(boost::function&lt;void(...)&gt; -> boost::function&lt;void()&gt;)

根据建议,我将Connection 函数更改为读取void statusPing(boost::function&lt;void()&gt;);,因为绑定了参数。此更改会产生不同的错误:

g++ -std=c++0x -DBOOST_LOG_DYN_LINK -I/home/donald/Desktop/workspace/MCProxy/Debug/ -O3 -march=corei7-avx -g1 -w -c -fmessage-length=0 -MMD -MP -MF"src/ClientServerManager.d" -MT"src/ClientServerManager.d" -o "src/ClientServerManager.o" "../src/ClientServerManager.cpp"
In file included from ....
/boost/bind/bind.hpp: In instantiation of ‘void boost::_bi::list4<A1, A2, A3, A4>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>; A = boost::_bi::list0; A1 = boost::_bi::value<ClientServerManager*>; A2 = boost::_bi::value<MCServer>; A3 = boost::_bi::value<boost::shared_ptr<Connection> >; A4 = boost::arg<1> (*)()]’:
/boost/bind/bind_template.hpp:20:59:   required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void; F = boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>; L = boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()>; boost::_bi::bind_t<R, F, L>::result_type = void]’
/boost/function/function_template.hpp:153:11:   required from ‘static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void]’
/boost/function/function_template.hpp:934:60:   required from ‘void boost::function0<R>::assign_to(Functor) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void]’
/boost/function/function_template.hpp:722:7:   required from ‘boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/boost/function/function_template.hpp:1071:16:   required from ‘boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, ClientServerManager, const MCServer&, boost::shared_ptr<Connection>&, const boost::system::error_code&>, boost::_bi::list4<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, boost::arg<1> (*)()> >; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
../src/ClientServerManager.cpp:90:2:   required from here
/boost/bind/bind.hpp:457:9: error: no match for ‘operator[]’ in ‘a[boost::_bi::storage4<A1, A2, A3, boost::arg<I> (*)()>::a4_<boost::_bi::value<ClientServerManager*>, boost::_bi::value<MCServer>, boost::_bi::value<boost::shared_ptr<Connection> >, 1>]’
/boost/bind/bind.hpp:457:9: note: candidates are:
In file included ....
/boost/bind/bind.hpp:170:27: note: template<class T> T& boost::_bi::list0::operator[](boost::_bi::value<T>&) const
/boost/bind/bind.hpp:170:27: note:   template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note:   mismatched types ‘boost::_bi::value<T>’ and ‘boost::arg<1>()’
In file included ....
/boost/bind/bind.hpp:172:33: note: template<class T> const T& boost::_bi::list0::operator[](const boost::_bi::value<T>&) const
/boost/bind/bind.hpp:172:33: note:   template argument deduction/substitution failed:
In file included ....
/boost/bind/bind.hpp:457:9: note:   mismatched types ‘const boost::_bi::value<T>’ and ‘boost::arg<1>()’
In file included ....
/boost/bind/bind.hpp:174:27: note: template<class T> T& boost::_bi::list0::operator[](const boost::reference_wrapper<T>&) const
/boost/bind/bind.hpp:174:27: note:   template argument deduction/substitution failed:
In file included from ....
/boost/bind/bind.hpp:457:9: note:   mismatched types ‘const boost::reference_wrapper<T>’ and ‘boost::arg<1>()’
In file included from ....
/boost/bind/bind.hpp:176:76: note: template<class R, class F, class L> typename boost::_bi::result_traits<R, F>::type boost::_bi::list0::operator[](boost::_bi::bind_t<R, F, L>&) const
/boost/bind/bind.hpp:176:76: note:   template argument deduction/substitution failed:
In file included from ....
/boost/bind/bind.hpp:457:9: note:   mismatched types ‘boost::_bi::bind_t<R, F, L>’ and ‘boost::arg<1>()’
/boost/bind/bind.hpp:178:76: note: template<class R, class F, class L> typename boost::_bi::result_traits<R, F>::type boost::_bi::list0::operator[](const boost::_bi::bind_t<R, F, L>&) const
/boost/bind/bind.hpp:178:76: note:   template argument deduction/substitution failed:
/boost/bind/bind.hpp:457:9: note:   mismatched types ‘const boost::_bi::bind_t<R, F, L>’ and ‘boost::arg<1>()’
make: *** [src/ClientServerManager.o] Error 1

一个简化的例子:

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <boost/function.hpp>

class ExampleWorker {
    public:
        void statusPing(boost::function<void()> f){
            // Do work.
            f(); // Call handle
        }
};

class SomeObject {};

void someHandle(boost::shared_ptr<SomeObject> obj,
        const boost::system::error_code& err){
    // ...
}

int main() {
    ExampleWorker* e = new ExampleWorker();
    boost::shared_ptr<SomeObject> ptr(new SomeObject());

    e->statusPing(
            boost::bind(
                &someHandle,
                ptr,
                boost::asio::placeholders::error
            )
    );
}

【问题讨论】:

  • 您正在绑定调用ClientServerManager::onPingCompletion() 所需的所有参数,因此从绑定表达式创建的可调用对象将转换为boost::function&lt;void()&gt;。尝试对statusPing() 进行更改,您的代码应该可以编译。
  • 另外,这些都是编译器错误,而不是链接器错误。您的问题一开始有点令人困惑,因为您一直提到链接和链接错误。
  • 感谢@Praetorian 的指导。我仍然收到错误消息;你有什么额外的建议吗? error: no match for ‘operator[]’ in ‘a[boost::_bi::storage4&lt;A1, A2, A3, boost::arg&lt;I&gt; (*)()&gt;::a4_&lt;boost::_bi::value&lt;ClientServerManager*&gt;, boost::_bi::value&lt;MCServer&gt;, boost::_bi::value&lt;boost::shared_ptr&lt;Connection&gt; &gt;, 1&gt;]’
  • 你能显示更新的代码吗?请注意,statusPing 必须接受 function&lt;void()&gt;,或者您应该创建一个接受 3 个参数的绑定器,例如 bind(this, _1, _2, _3) - 取决于您实际打算如何调用该函子。
  • 是导致新错误的同一行吗?您能否尝试创建一个重现该问题的SSCCE

标签: c++ boost boost-asio


【解决方案1】:

boost::asio::placeholders::error 就像使用 boost::placeholders::_1boost::bind 一样,当您将包含它的绑定表达式传递给 asio 完成处理函数时,该函数将使用来自它执行的操作,从而允许您的处理程序访问错误代码。

在您的第二个示例中,boost::function 签名用于以下 bind 表达式

boost::bind(
    &someHandle,
    ptr,
    boost::asio::placeholders::error
)

boost::function<void(boost::system::error_code const&)>

要编译您的代码,请将statusPing() 成员函数更改为

void statusPing(boost::function<void(boost::system::error_code const&)> f){
    // Do work.
    boost::system::error_code err;
    f(err); // Call handle
}

【讨论】:

猜你喜欢
  • 2016-03-16
  • 1970-01-01
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多