views:

172

answers:

2

How do I get boost::bind to work with array subscripts? Here's what I'm trying to achieve. Please advice.

[servenail: C++Progs]$ g++ -v
Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.6/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr /share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386- redhat-linux
Thread model: posix
gcc version 3.4.6 20060404 (Red Hat 3.4.6-3)

[servenail: C++Progs]$ cat t-array_bind.cpp

#include <map>
#include <string>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <iostream>

using namespace std;
using namespace boost;
using namespace boost::lambda;

class X
{
public:
    X(int x0) : m_x(x0)
    {
    }

    void f()
    {
        cout << "Inside function f(): object state = " << m_x << "\n";
    }

private:
    int m_x;
};

int main()
{
    X x1(10);
    X x2(20);
    X* array[2] = {&x1, &x2};

    map<int,int> m;
    m.insert(make_pair(1, 0));
    m.insert(make_pair(2, 1));

    for_each(m.begin(),
             m.end(),
             array[bind(&map<int,int>::value_type::second, _1)]->f());
}

[servenail: C++Progs]$ g++ -o t-array_bind t-array_bind.cpp t-array_bind.cpp: In function `int main()': t-array_bind.cpp:40: error: no match for 'operator[]' in
'array[boost::lambda::bind(const Arg1&, const Arg2&) >&">with Arg1 = int std::pair::*, Arg2 = boost::lambda::lambda_functor >(+boost::lambda::::_1)))]'

Thanks a lot.

+1  A: 

The reason your code doesn't compile is because the return value of boost::bind is not an integer type that can be used as an array subscript. Rather, boost::bind returns an implementation-defined function object of an unspecified type, which can be called using the () operator.

Charles Salvia
+1  A: 

As Charles has explained, boost::bind returns a function object and not an integer. The function object will be evaluated for each member. A little helper struct will solve the problem:

struct get_nth {
    template<class T, size_t N>
    T& operator()( T (&a)[N], int nIndex ) const {
        assert(0<=nIndex && nIndex<N);
        return a[nIndex];
    }
}

for_each(m.begin(),
         m.end(),
         boost::bind( 
             &X::f,
             boost::bind( 
                 get_nth(), 
                 array, 
                 bind(&map<int,int>::value_type::second, _1) 
             )
         ));

Edit: I've changed the functor to return the nth element of the array.

Sebastian
yes, i'm aware of the fact that bind returns a function object. I wrote my original code in that way to make my objectives clear. I was hoping if this could be achieved w/o a call to a separate function. I guess not.
posharma