Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::bind doesn't work with boost::tuple::get<N>()

I am trying to use boost::bind and STL with boost::tuple, but each time I try to compile I get the following error.

      error: call of overloaded ‘bind(<unresolved overloaded function type>, 
      boost::arg<1>&)’ is ambiguous

Do you know what I am doing wrong here and why is only for the boost::arg<1>?

Thanks AFG

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cstdio>
    #include <boost/tuple/tuple.hpp>
    #include <boost/assign.hpp>
    #include <boost/bind.hpp>

    int main( int argc, const char** argv ){


            using namespace boost::assign;
            typedef boost::tuple< int, double > eth_array;

            std::vector< eth_array > v;
            v+= boost::make_tuple( 10,23.4), boost::make_tuple( 12,24.4) );
            std::for_each( v.begin()
                    , v.end()
                    , boost::bind<int>(
                            printf
                            , "%d-%f"
                            , boost::bind( eth_array::get<0>, _1 )
                            , boost::bind( eth_array::get<1>, _1 )
                     )
            );
like image 340
Abruzzo Forte e Gentile Avatar asked Jan 18 '23 22:01

Abruzzo Forte e Gentile


1 Answers

The get function has more than one template parameter: in addition to the index, it is also parameterized on the content of the tuple (the head and the tail of the cons).

Consequently, get<0> is not an instantiation of the template; you need to provide the additional arguments:

typedef eth_array::head_type head;
typedef eth_array::tail_type tail;

... get<0, head, tail> ...

However, this still won't work because get is overloaded (const and non-const version), so you need to explicitely state which overload you want. To do so, you need to use a function pointer with the correct type:

// const version of get, which takes and returns const references
int const & (*get0)( boost::tuples::cons<head, tail> const & ) = 
    boost::get<0, head, tail>;
double const & (*get1)( boost::tuples::cons<head, tail> const & ) = 
    boost::get<1, head, tail>;

Now you can use these function pointers in your bind expression:

std::for_each( v.begin(),
               v.end(),
               boost::bind<int>(
                   printf,
                   "%d-%f",
                   boost::bind( get0, _1 ),
                   boost::bind( get1, _1 )
               )
);
// outputs 10-23.40000012-24.400000

As you can see, overloaded function templates and bind does not get along very well...

like image 152
Luc Touraille Avatar answered Jan 28 '23 02:01

Luc Touraille