tags:

views:

198

answers:

2

To take apart a pair, the following can be done

boost::bind(&std::pair::second, _1); // returns the value of a pair

What about using combinations of different containers, how can a nested pair be accessed?

For example when I wanted to partition a vector into items contained in a supplemental map and items that where not contained in the supplemental map I used the following:

typedef int DWORD; typedef std::pair<std::string, bool> user_info; 
typedef std::map<DWORD, user_info> USER_MAP; 
typedef std::vector<DWORD> VEC_STAFF; 
VEC_STAFF::iterator it = std::partition(
   Staff.begin(), Staff.end(), 
  (bind(&USER_MAP::find, m_Users, _1) != m_Users.end()));

Now I have a second problem - during the running of the application the status bool of user_info can change, and later on I want to re-partition the vector with items that have a status bool of true rather than just being contained in the supplemental map.

However I seem to have a problem accessing the second item of a nested pair.

I tried the following but I cannot seem to access the nested pair!

VEC_STAFF::const_iterator itCurEnd = partition(Staff.begin(), Staff.end(),
     bind(&USER_MAP::value_type::second::second, 
     bind(&USER_MAP::find, &m_Users, _1)) == true);
+1  A: 

The syntax you used obviously doesn't work. The first "::second" already signifies a non-static member and not a type. If you have a pair inside a pair you probably have to use two bind calls:

typedef std::pair< int, bool > foo_t;
typedef std::pair< int, foo_t > bar_t;
.....

bind( &foo_t::second, bind(&bar_t::second,
    bind( &USER_MAP::find, _1 )
) )

(I didn't test this. Perhaps this is what you want)

But three levels if bind is quite challenging, in my opinion.

Edit: How about this?

template<typename Iter, typename Return>
struct deref_2nd_2nd : std::unary_function<Iter, Return> {
    Return operator()(Iter const& it) const {
        return (*it).second.second;
    }
};

.....

bind(
    deref_2nd_2nd<USER_MAP::iterator,bool>(),
    bind( &USER_MAP::find, _1 )
)
sellibitze
As Glen said, it's probably better to write your own class as predicate. It's not clear from your code what you were trying to do. find returns an iterator which is not a pair. (Dereferencing is missing)
sellibitze
Your right, I realised this later on. But now I'm even more confused than before. In my first call to partition the bind call is returning an iterator. As you say find returns in iterator, but its function argument is a value, and not an iterator so how is the vector iterator being dereferenced?I suppose what I want is to dereference the iterator which would result in a pair, and then I want to compare the .second part of the pair against true
Stone Free
I don't know what it is that you want. What about the cases where find returns an iterator that compares equal to USER_MAP.end()?
sellibitze
There will never be any items in the vector that are not present in the map. This precondition has been enforced earlier on.This second partitioning is based on data that has changed in the value (not the key), no keys will have been removed from the map, or the vector
Stone Free
+4  A: 

Not sure I follow what's going on there, but usually when I start running into problems with bind I give up and implement a functor. This might simplify things in your case.

To me, the following is a lot easier to read than all that messing around with multiple levels of binds

template <class Arg>
struct Whatever : public std::unary_function<Arg, bool>
{
    bool operator()(const Arg &arg1) const {
        //logic here
    } 
};

Whatever<???> functor;
std::partition(Staff.begin(), Staff.end(), functor);
Glen
Definitely. Bind is nice in simple cases, and sometimes boost::tie can be helpful, but when the syntax gets too hairy, write your own functor instead.
jalf
+1 For the back out at try something slightly different.
Chris Huang-Leaver