2009-09-22 4 views
0

Pour démonter une paire, ce qui suit peut être faitAccès à une paire imbriquée

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

Qu'en est-il en utilisant des combinaisons de récipients différents, comment une paire imbriquée est accessible?

Par exemple, quand je voulais partitionner un vecteur dans les éléments contenus dans une carte supplémentaire et les éléments que lorsqu'ils ne sont pas contenues dans la carte supplémentaire j'ai utilisé les éléments suivants:

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())); 

Maintenant, j'ai un deuxième problème - au cours l'exécution de l'application le statut bool de user_info peut changer, et plus tard je veux re-partitionner le vecteur avec des éléments qui ont un bool de statut de vrai plutôt que d'être simplement contenus dans la carte supplémentaire.

Cependant, je semble avoir un problème pour accéder au second élément d'une paire imbriquée.

J'ai essayé ce qui suit, mais je n'arrive pas à accéder à la paire imbriquée!

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); 

Répondre

1

La syntaxe utilisée ne fonctionne évidemment pas. Le premier ":: second" signifie déjà un membre non statique et pas un type. Si vous avez une paire dans une paire vous avez probablement utiliser deux appels bind:

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) 
)) 

(. Je n'ai pas testé ce cela est peut-être ce que vous voulez)

Mais trois niveaux se lient est tout à fait difficile, à mon avis.

Éditer: Que pensez-vous de cela?

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) 
) 
+1

Comme Glen dit, il est probablement préférable d'écrire votre propre classe comme prédicat. Votre code n'indique pas clairement ce que vous essayez de faire. find renvoie un itérateur qui n'est pas une paire. (Déréférencement est manquant) – sellibitze

+0

Votre droite, je l'ai réalisé plus tard. Mais maintenant je suis encore plus confus qu'avant. Dans mon premier appel à partitionner l'appel de bind retourne un itérateur. Comme vous le dites, find retourne dans l'itérateur, mais son argument de fonction est une valeur, et non un itérateur, alors comment l'itérateur de vecteur est-il déréférencé? Je suppose que ce que je veux est de déréférencer l'itérateur qui résulterait en une paire, et ensuite je veux comparer la seconde partie de la paire par rapport à la vraie –

+0

Je ne sais pas ce que vous voulez. Qu'en est-il des cas où find renvoie un itérateur égal à USER_MAP.end()? – sellibitze

4

Je ne sais pas je suivre ce qui se passe là-bas, mais en général quand je commence à avoir des problèmes avec bind je donne et mettre en œuvre un foncteur. Cela pourrait simplifier les choses dans votre cas.

Pour moi, ce qui suit est beaucoup plus facile à lire que tout ce qui déconner avec plusieurs niveaux de 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); 
+0

Définitivement. La liaison est agréable dans les cas simples, et parfois boost :: tie peut être utile, mais quand la syntaxe devient trop poilue, écrivez votre propre foncteur à la place. – jalf

+0

+1 Pour le retrait à essayer quelque chose de légèrement différent. –

Questions connexes