Question

I'm trying to chain together curried functions using boost::bind, and getting compiler errors that I can't resolve. The simplest example I can make which fails to compile:

#include <iostream>
#include <boost/bind.hpp>

class A
{
public:
    template <typename F>
    void g(F fn, char c)
    {
        fn(c);
    }

    void h(char c)
    {
        std::cout << c << std::endl;
    }

    template <typename F>
    void f(F fn, char c)
    {
        boost::bind(&A::g<F>, this, fn, ::_1)(c);
    }
};

int main(int argc, char** argv)
{
    char c = 'a';
    A a;
    a.f(boost::bind(&A::h, &a, ::_1), c);
}

fails with this error:

In file included from /usr/include/boost/bind.hpp:22,
                 from test8.cpp:2:
/usr/include/boost/bind/bind.hpp: In member function ‘void boost::_bi::list3<A1, A2, A3>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf2<void, A, boost::_bi::bind_t<void, boost::_mfi::mf1<void, A, char>, boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > >, char>, A = boost::_bi::list1<char&>, A1 = boost::_bi::value<A*>, A2 = boost::_bi::bind_t<void, boost::_mfi::mf1<void, A, char>, boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > >, A3 = boost::arg<1>]’:
/usr/include/boost/bind/bind_template.hpp:32:   instantiated from ‘typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()(A1&) [with A1 = char, R = void, F = boost::_mfi::mf2<void, A, boost::_bi::bind_t<void, boost::_mfi::mf1<void, A, char>, boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > >, char>, L = boost::_bi::list3<boost::_bi::value<A*>, boost::_bi::bind_t<void, boost::_mfi::mf1<void, A, char>, boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > >, boost::arg<1> >]’
test8.cpp:21:   instantiated from ‘void A::f(F, char) [with F = boost::_bi::bind_t<void, boost::_mfi::mf1<void, A, char>, boost::_bi::list2<boost::_bi::value<A*>, boost::arg<1> > >]’
test8.cpp:29:   instantiated from here
/usr/include/boost/bind/bind.hpp:385: error: invalid use of void expression

This is using

$ g++ --version
g++ (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
Was it helpful?

Solution

You need to use boost::protect() in such cases, when you pass a bind expression to another bind call but don't want the nested one to be invoked during the evaluation of arguments to the outer bound function, but rather want the nested bind expression to be passed as-is as an argument to the outer bound function. Here it will be:

boost::bind(&A::g<F>, this, boost::protect(fn), ::_1)(c);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top