views:

291

answers:

1

I have some code that looks like this:

typedef tuple<int, int, double> DataPoint;
vector<DataPoint> data;
vector<double> third_column_only;
// Code to read in data goes here.
transform(data.begin(), data.end(), back_inserter(values), tuples::get<1, DataPoint>);

Unfortunately, the last line doesn't compile - it gives me a message like this:

/path/to/boost/tuple/detail/tuple_basic.hpp: In instantiation of `boost::tuples::cons':
/path/to/boost/tuple/detail/tuple_basic.hpp:144:   instantiated from `boost::tuples::element >'
program.cc:33:   instantiated from here
/path/to/boost/tuple/detail/tuple_basic.hpp:329: error: `boost::tuples::cons::tail' has incomplete type
/path/to/boost/tuple/detail/tuple_basic.hpp:329: error: invalid use of template type parameter
/path/to/boost/tuple/detail/tuple_basic.hpp:151: confused by earlier errors, bailing out

Basically, to use Python's operator.itemgetter function, I want to do something like this:

transform(data.begin(), data.end(), back_inserter(values), itemgetter(2))

How can I do that using Boost?

+1  A: 

You need a boost::bind to do this.

double get2(boost::tuple<int,int,double> const& v ) {
    return boost::get<2>(v) ;
}

int main () {
    using namespace std ;
    using namespace boost ;
    typedef tuple<int, int, double> DataPoint;
    vector<DataPoint> data;
    vector<double> third_column_only;
    // Code to read in data goes here.
    transform(data.begin(), data.end(), back_inserter(values), bind(get2, _1);
}

Acturally, the get2 function is also unnecessary, but we have to specify the exactly template argument for the boost::get function, possiblly like:

transform(data.begin(), data.end(), back_inserter(values), 
          bind(get<2, int, tuple<int, double> >, _1);

It's a shame that I don't how to specify the template argument, so I used a helper function. Sorry about that.

yoco
Thanks - boost::bind was what I was looking for, as was the template declaration for get<2, int, tuple<int, double> > - I wasn't aware that get's template decl was get<N, Head, Tail> instead of get<N, MyType>.However, even with bind, I still can't seem to get it to compile without adding a get2-like function declaration. I'm using gcc 3.4 under cygwin, so it might be a compiler version issue - still, just using bind(get<2, int, tuple<int, double> >, _1)Gives me a compiler error along the lines of "unknown call to bind with first argument of type unknown".
Steve