Boost function and bind issue

Discussion in 'C++' started by Chris Ahlstrom, Sep 5, 2010.

  1. This code compiles:

    boost::asio::ip::tcp::acceptor m_acceptor; // declared in a class

    connector::pointer new_conn(new connector(m_acceptor.io_service()));
    m_acceptor.async_accept
    (
    new_conn->socket(),
    boost::bind
    (
    &timingserver::handle_accept,
    this,
    boost::asio::placeholders::error,
    new_conn
    )
    );

    So now I want to pull out the boost::bind part and make a function object of it.

    boost::function
    <
    void
    (
    const boost::system::error_code &,
    boost::asio::ip::tcp::resolver::iterator endpoint_iterator
    )
    > b = boost::bind

    (
    &timingserver::handle_accept,
    this,
    boost::asio::placeholders::error,
    new_conn
    );
    m_acceptor.async_accept(new_conn->socket(), b);

    The ultimate error I get is

    /usr/include/boost/asio/detail/bind_handler.hpp:39: error: no match for call to

    '(
    boost::function
    <
    void
    (
    const boost::system::error_code&,
    boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
    )
    >i

    ) (boost::system::error_code&)'

    /usr/include/boost/function/function_template.hpp:1006: note: candidates are:

    R boost::function2<R, T1, T2>::eek:perator()(T0, T1) const

    [with R = void,
    T0 = const boost::system::error_code&,
    T1 = boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>]

    I've been able to make similar function objects from other bound functions,
    so I'm a bit puzzled here.

    --
    Grelb's Reminder:
    Eighty percent of all people consider themselves to be above
    average drivers.
    Chris Ahlstrom, Sep 5, 2010
    #1
    1. Advertising

  2. Chris Ahlstrom <>, on 05/09/2010 11:48:31, wrote:

    > This code compiles:


    Uhm, no, as it is, it doesn't ;-)

    Please see FAQ 5.8 and post complete code.

    >
    > boost::asio::ip::tcp::acceptor m_acceptor; // declared in a class
    >
    > connector::pointer new_conn(new connector(m_acceptor.io_service()));
    > m_acceptor.async_accept
    > (
    > new_conn->socket(),
    > boost::bind
    > (
    > &timingserver::handle_accept,
    > this,
    > boost::asio::placeholders::error,
    > new_conn
    > )
    > );
    >
    > So now I want to pull out the boost::bind part and make a function object of it.
    >
    > boost::function
    > <
    > void
    > (
    > const boost::system::error_code&,
    > boost::asio::ip::tcp::resolver::iterator endpoint_iterator
    > )
    > > b = boost::bind

    > (
    > &timingserver::handle_accept,
    > this,
    > boost::asio::placeholders::error,
    > new_conn
    > );
    > m_acceptor.async_accept(new_conn->socket(), b);
    >
    > The ultimate error I get is
    >
    > /usr/include/boost/asio/detail/bind_handler.hpp:39: error: no match for call to
    >
    > '(
    > boost::function
    > <
    > void
    > (
    > const boost::system::error_code&,
    > boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
    > )
    > >i

    > ) (boost::system::error_code&)'
    >
    > /usr/include/boost/function/function_template.hpp:1006: note: candidates are:
    >
    > R boost::function2<R, T1, T2>::eek:perator()(T0, T1) const
    >
    > [with R = void,
    > T0 = const boost::system::error_code&,
    > T1 = boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>]
    >
    > I've been able to make similar function objects from other bound functions,
    > so I'm a bit puzzled here.
    >


    Don't know, I would try to solve it for you but I've not enough time to
    make something compilable out of your code.

    Post a complete misbehaving example and we will try to help you - by the
    way, there are boost mailing lists and groups out there, just to let you
    know; you will get help here eventually but you should ease our
    reviewing task a bit.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Sep 5, 2010
    #2
    1. Advertising

  3. Francesco S. Carta posted this message in ROT13 encoding:

    > Chris Ahlstrom <>, on 05/09/2010 11:48:31, wrote:
    >
    >> This code compiles:

    >
    > Uhm, no, as it is, it doesn't ;-)
    >
    > Please see FAQ 5.8 and post complete code.


    Actually, I'm hopeful that this problem is easier resolved by inspection
    from someone who's been through the issue before.

    Why does the passing of the bind object directly to async_accept() compile
    fine, while making a real object out of it, using boost::function, and
    passing that, not work.

    Hmmmm. I'm thinking now I may know why. A misapprehension ... My
    boost::function call isn't creating a function object compatible with
    async_write(). The other ones I got work were passed to functions that
    I wrote, and so could control the function signature.

    But I've got to go play some soccer first. My brain will probably work
    better afterwards anyway.

    > Don't know, I would try to solve it for you but I've not enough time to
    > make something compilable out of your code.


    Oh, I understand. I only post questions when I'm stumped, and think the
    answer would be obvious to somebody else.

    > Post a complete misbehaving example and we will try to help you - by the
    > way, there are boost mailing lists and groups out there, just to let you
    > know; you will get help here eventually but you should ease our
    > reviewing task a bit.


    I can't find any *boost* (regexp) newsgroups in Usenet. I'm not a big fan
    of visiting fora and wikis through my browser.

    Thanks for responding! If I figure it out, I'll at least post the answer
    here.

    --
    Smoking is the leading cause of statistics.
    Chris Ahlstrom, Sep 5, 2010
    #3
  4. Chris Ahlstrom <>, on 05/09/2010 17:26:52, wrote:

    > Francesco S. Carta posted this message in ROT13 encoding:
    >
    >> Chris Ahlstrom<>, on 05/09/2010 11:48:31, wrote:
    >>
    >>> This code compiles:

    >>
    >> Uhm, no, as it is, it doesn't ;-)
    >>
    >> Please see FAQ 5.8 and post complete code.

    >
    > Actually, I'm hopeful that this problem is easier resolved by inspection
    > from someone who's been through the issue before.


    As you prefer, but by not following the guidelines you're actively
    narrowing down the frame of potential responses. Furthermore, you're
    surely not a newbie, so you might take the chance to "act as expected"
    when you happen to ask for help - showing thus an example of "good
    asking style".

    As you can see you did not get any valuable reply yet: consider that
    somebody could well know what you're after and could deliberately omit
    to post a reply just because you didn't follow the mentioned guidelines.
    (!!!)

    > Why does the passing of the bind object directly to async_accept() compile
    > fine, while making a real object out of it, using boost::function, and
    > passing that, not work.
    >
    > Hmmmm. I'm thinking now I may know why. A misapprehension ... My
    > boost::function call isn't creating a function object compatible with
    > async_write(). The other ones I got work were passed to functions that
    > I wrote, and so could control the function signature.
    >
    > But I've got to go play some soccer first. My brain will probably work
    > better afterwards anyway.
    >
    >> Don't know, I would try to solve it for you but I've not enough time to
    >> make something compilable out of your code.

    >
    > Oh, I understand. I only post questions when I'm stumped, and think the
    > answer would be obvious to somebody else.


    Sure, but maybe somebody less experienced and willing to investigate
    (just like me) would have taken advantage of feeding your code to a
    compiler and fiddling with it ;-)

    >> Post a complete misbehaving example and we will try to help you - by the
    >> way, there are boost mailing lists and groups out there, just to let you
    >> know; you will get help here eventually but you should ease our
    >> reviewing task a bit.

    >
    > I can't find any *boost* (regexp) newsgroups in Usenet. I'm not a big fan
    > of visiting fora and wikis through my browser.


    Mailing lists aren't all that different from Usenet groups... maybe that
    would pollute your inbox for some time before you get a meaningful reply
    and decide to stop reading the list, but that would be a minor problem,
    easily solvable.

    > Thanks for responding! If I figure it out, I'll at least post the answer
    > here.


    Well, for what is worth, you're welcome!
    I look forward to see the solution to this issue.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Sep 5, 2010
    #4
  5. Francesco S. Carta posted this message in ROT13 encoding:

    >> Thanks for responding! If I figure it out, I'll at least post the answer
    >> here.

    >
    > Well, for what is worth, you're welcome!
    > I look forward to see the solution to this issue.


    I'm more confused than ever, as I see that the Boost sockets'
    async_accept()'s second parameter is a templated type. So I should be
    able to directly pass a boost::function-wrapped object to async_write().

    Neither the soccer nor a night's rest is doing the trick.

    --
    yo-yo, n.:
    Something that is occasionally up but normally down.
    (see also Computer).
    Chris Ahlstrom, Sep 6, 2010
    #5
  6. Chris Ahlstrom <>, on 06/09/2010 09:41:16, wrote:

    > Francesco S. Carta posted this message in ROT13 encoding:
    >
    >>> Thanks for responding! If I figure it out, I'll at least post the answer
    >>> here.

    >>
    >> Well, for what is worth, you're welcome!
    >> I look forward to see the solution to this issue.

    >
    > I'm more confused than ever, as I see that the Boost sockets'
    > async_accept()'s second parameter is a templated type. So I should be
    > able to directly pass a boost::function-wrapped object to async_write().
    >
    > Neither the soccer nor a night's rest is doing the trick.
    >


    Several walkable paths:

    - go on waiting for someone to drop the solution here on the base of the
    info you provided thus far;

    - post here some complete minimal misbehaving program to let people
    fiddle with it - as you should know, cutting down your program could
    actually bring you to the solution - if that doesn't work, you'll have
    the minimal program ready to be posted here;

    - bring your issue to one of the mailing lists available here:
    http://www.boost.org/community/groups.html

    (I must also point out that you didn't mention which compiler is
    refusing your code)

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Sep 6, 2010
    #6
  7. On 5 sep, 17:48, Chris Ahlstrom <> wrote:
    [snip]
    > So now I want to pull out the boost::bind part and make a function object of it.
    >
    >    boost::function
    >    <
    >       void
    >       (
    >          const boost::system::error_code &,
    >          boost::asio::ip::tcp::resolver::iterator endpoint_iterator
    >       )
    >    > b = boost::bind
    >    (
    >       &timingserver::handle_accept,
    >       this,
    >       boost::asio::placeholders::error,
    >       new_conn
    >    );
    >    m_acceptor.async_accept(new_conn->socket(), b);
    >
    > The ultimate error I get is
    >
    > /usr/include/boost/asio/detail/bind_handler.hpp:39: error: no match for call to
    >
    >  '(
    >       boost::function
    >       <
    >          void
    >          (
    >             const boost::system::error_code&,
    >              boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>
    >          )
    >       >i
    >    ) (boost::system::error_code&)'
    >
    > /usr/include/boost/function/function_template.hpp:1006: note: candidates are:
    >
    >    R boost::function2<R, T1, T2>::eek:perator()(T0, T1) const
    >
    >  [with R = void,
    >        T0 = const boost::system::error_code&,
    >        T1 = boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>]
    >
    > I've been able to make similar function objects from other bound functions,
    > so I'm a bit puzzled here.


    *According to documentation*, async_accept takes as parameter a
    AcceptHandler:
    "An accept handler must meet the requirements for a handler. A value h
    of an accept handler class should work correctly in the expression
    h(ec), where ec is an lvalue of type const error_code."

    With Boost.Function, the type should be:
    boost::function1<void,boost::system::error_code>
    or as you put it:
    boost::function<void(const boost::system::error_code&)>

    RTFM. Really do it.

    --
    Michael
    Michael Doubez, Sep 6, 2010
    #7
  8. Michael Doubez posted this message in ROT13 encoding:

    > On 5 sep, 17:48, Chris Ahlstrom <> wrote:
    > [snip]
    >>
    >> I've been able to make similar function objects from other bound functions,
    >> so I'm a bit puzzled here.

    >
    > *According to documentation*, async_accept takes as parameter a
    > AcceptHandler:
    > "An accept handler must meet the requirements for a handler. A value h
    > of an accept handler class should work correctly in the expression
    > h(ec), where ec is an lvalue of type const error_code."
    >
    > With Boost.Function, the type should be:
    > boost::function1<void,boost::system::error_code>
    > or as you put it:
    > boost::function<void(const boost::system::error_code&)>
    >
    > RTFM. Really do it.


    Thanks. But what I really wanted to do was (1) bind a class member function
    into a function that met those requirements, and (2) save the bound function
    for later invocation inside async_write().

    The first was easy, even with extra arguments; the second I'm having trouble
    with.

    --
    The greatest dangers to liberty lurk in insidious encroachment by men
    of zeal, well-meaning but without understanding.
    -- Justice Louis D. Brandeis
    Chris Ahlstrom, Sep 6, 2010
    #8
  9. Chris Ahlstrom posted this message in ROT13 encoding:

    > Michael Doubez posted this message in ROT13 encoding:
    >
    >> With Boost.Function, the type should be:
    >> boost::function1<void,boost::system::error_code>


    That's the "portable" version, for backward compilers.

    >> or as you put it:
    >> boost::function<void(const boost::system::error_code&)>


    That's the normal version.

    > Thanks. But what I really wanted to do was (1) bind a class member function
    > into a function that met those requirements, and (2) save the bound function
    > for later invocation inside async_write().


    Finally got it to compile. The original version (actually based on
    boost/asio/examples/serialization/server.cpp) that was easy was:

    connector::pointer new_conn(new connector(m_acceptor.io_service()));

    m_acceptor.async_accept
    (
    new_conn->socket(),
    boost::bind
    (
    &timingserver::handle_accept,
    this,
    boost::asio::placeholders::error,
    new_conn
    )
    );

    This storage of the bound function compiles:

    boost::function<void(const boost::system::error_code & e)> b =
    boost::bind
    (
    &timingserver::handle_accept,
    this,
    boost::asio::placeholders::error,
    new_conn
    );
    m_acceptor.async_accept
    (
    new_conn->socket(),
    b
    );

    This is with g++ (Debian 4.4.4-8) 4.4.5 20100728 (prerelease).
    Hope it actually runs. I don't get why it works. :-(

    Thanks for all the advice. It actually helped!

    --
    ... I used to get in more fights with SCO than I did my girlfriend, but
    now, thanks to Linux, she has more than happily accepted her place back at
    number one antagonist in my life..
    -- Jason Stiefel,
    Chris Ahlstrom, Sep 7, 2010
    #9
  10. On 7 sep, 01:15, Chris Ahlstrom <> wrote:
    > Chris Ahlstrom posted this message in ROT13 encoding:
    >
    > > Michael Doubez posted this message in ROT13 encoding:

    >
    > >> With Boost.Function, the type should be:
    > >> boost::function1<void,boost::system::error_code>

    >
    > That's the "portable" version, for backward compilers.
    >
    > >> or as you put it:
    > >> boost::function<void(const boost::system::error_code&)>

    >
    > That's the normal version.
    >
    > > Thanks.  But what I really wanted to do was (1) bind a class member function
    > > into a function that met those requirements, and (2) save the bound function
    > > for later invocation inside async_write().

    >
    > Finally got it to compile.  The original version (actually based on
    > boost/asio/examples/serialization/server.cpp) that was easy was:
    >
    >    connector::pointer new_conn(new connector(m_acceptor.io_service()));
    >
    >    m_acceptor.async_accept
    >    (
    >       new_conn->socket(),
    >       boost::bind
    >       (
    >          &timingserver::handle_accept,
    >          this,
    >          boost::asio::placeholders::error,
    >          new_conn
    >       )
    >    );
    >
    > This storage of the bound function compiles:
    >
    >    boost::function<void(const boost::system::error_code & e)> b =
    >       boost::bind
    >       (
    >          &timingserver::handle_accept,
    >          this,
    >          boost::asio::placeholders::error,
    >          new_conn
    >       );
    >    m_acceptor.async_accept
    >    (
    >       new_conn->socket(),
    >       b
    >    );
    >
    > This is with g++ (Debian 4.4.4-8) 4.4.5 20100728 (prerelease).
    > Hope it actually runs.  I don't get why it works.  :-(


    What works ? The change ?

    Truly, there is not much to understand: async_accept expects a functor
    that takes one parameter (a boost::system::error_code). This is what
    bind() provides; in your example it instantiate a boost::function that
    calls this->handle_accept( _ , new_conn) where _ is the placeholder
    for the future boost::system::error_code parameter.

    If you want to store it, you have to know the type of the variable
    that will store it (unless you use C++0x's auto); the relevant type is
    boost::function<void(const boost::system::error_code&)>.

    --
    Michael
    Michael Doubez, Sep 7, 2010
    #10
  11. Michael Doubez posted this message in ROT13 encoding:

    > On 7 sep, 01:15, Chris Ahlstrom <> wrote:
    >
    >> Finally got it to compile.  The original version (actually based on
    >> boost/asio/examples/serialization/server.cpp) that was easy was:
    >>
    >>    connector::pointer new_conn(new connector(m_acceptor.io_service()));
    >>
    >>    m_acceptor.async_accept
    >>    (
    >>       new_conn->socket(),
    >>       boost::bind
    >>       (
    >>          &timingserver::handle_accept,
    >>          this,
    >>          boost::asio::placeholders::error,
    >>          new_conn
    >>       )
    >>    );
    >>
    >> This storage of the bound function compiles:
    >>
    >>    boost::function<void(const boost::system::error_code & e)> b =
    >>       boost::bind
    >>       (
    >>          &timingserver::handle_accept,
    >>          this,
    >>          boost::asio::placeholders::error,
    >>          new_conn
    >>       );
    >>    m_acceptor.async_accept
    >>    (
    >>       new_conn->socket(),
    >>       b
    >>    );
    >>
    >> This is with g++ (Debian 4.4.4-8) 4.4.5 20100728 (prerelease).
    >> Hope it actually runs.  I don't get why it works.  :-(

    >
    > What works ? The change ?
    >
    > Truly, there is not much to understand...


    You seem to be a knowledgeable fellow.
    So perhaps you can tell me how the boost::function object
    get the correct parameter to the actual call that async_write() makes.

    > : async_accept expects a functor
    > that takes one parameter (a boost::system::error_code). This is what
    > bind() provides; in your example it instantiate a boost::function that
    > calls this->handle_accept( _ , new_conn) where _ is the placeholder
    > for the future boost::system::error_code parameter.


    But how does the correct parameter get substituted? I found that
    other template parameters for boost::function also compiled correctly,
    though the result was unsuitable for async_write().

    <repetition snipped>

    --
    Ray's Rule of Precision:
    Measure with a micrometer. Mark with chalk. Cut with an axe.
    Chris Ahlstrom, Sep 7, 2010
    #11
  12. Michael Doubez posted this message in ROT13 encoding:

    > On 7 sep, 13:22, Chris Ahlstrom <> wrote:
    >>
    >> So perhaps you can tell me how the boost::function object
    >> get the correct parameter to the actual call that async_write() makes.

    >
    > Yes but a complete explanation is an awful lot of template :)
    >
    > Basically, boost::functionN<R,P1,2,...,PN> stores a pointer to an
    > interface defining a virtual R fN(P1,P2...) - this is type erasure.
    >
    > The problem is then to instantiate the correct function object which
    > is done with templated constructors and more generaly boost::bind().
    > The generated object/class are on the model of good old
    > std::mem_fun(), std::bind1st() ...
    >
    > It is easier with boost:bind() placeholder: _1, _2 ....
    > The parameter your pass are stores in the function object and the _1,
    > _2, _N placeholder determines which class must be instantiated:
    > instantiated with _1, the first parameter passed to the interface is
    > used, and so on.
    >
    > There may be some element in:"C++ Template Metaprogramming: Concepts,
    > Tools, and Techniques from Boost and Beyond"
    > I don't remember.


    Thanks!

    I bought a copy of "Beyond the C++ Standard Library: An Introduction to
    Boost", quite awhile back, and it is a great resource to start with, opened
    my eyes quite a bit, but it is still only an introduction, and the examples
    are a bit too simple.

    So I really appreciate your help.

    --
    "The reasonable man adapts himself to the world; the unreasonable one persists
    in trying to adapt the world to himself. Therefore all progress depends on
    the unreasonable man."
    -- George Bernard Shaw
    Chris Ahlstrom, Sep 7, 2010
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Toby Bradshaw
    Replies:
    6
    Views:
    1,712
    Kai-Uwe Bux
    Jun 2, 2006
  2. Replies:
    4
    Views:
    405
  3. Replies:
    0
    Views:
    573
  4. Christopher
    Replies:
    1
    Views:
    781
    Yakov Gerlovin
    Oct 5, 2011
  5. Mark
    Replies:
    1
    Views:
    415
    Jeff Flinn
    Nov 25, 2012
Loading...

Share This Page