2008-12-16 4 views
10

Weiß jemand, ob es ein De-facto-Standard (d. H., TR1 oder Boost) C++ - Funktionsobjekt für den Zugriff auf die Elemente eines std :: -Paares gibt? Zweimal in den letzten 24 Stunden habe ich mir gewünscht, ich hätte so etwas wie die keys Funktion für Perl Hashes. Zum Beispiel wäre es schön, std :: transform auf einem std :: map-Objekt auszuführen und alle Schlüssel (oder Werte) in einem anderen Container abzulegen. Ich könnte sicherlich solch ein Funktionsobjekt schreiben, aber ich würde es vorziehen, etwas wiederzuverwenden, das viele Augäpfel darauf hatte.Gibt es ein C++ - Standardfunktionsobjekt zum Zerlegen eines std :: -Paares?

Antwort

17

boost::bind ist, was Sie suchen.

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

Beispiel:

typedef std::map<std::string, int> map_type; 

std::vector<int> values; // will contain all values 
map_type map; 
std::transform(map.begin(), 
       map.end(), 
       std::back_inserter(values), 
       boost::bind(&map_type::value_type::second, _1)); 
4

Von der Art, wie Sie Ihre Frage formuliert haben, bin ich nicht sicher, ob dies eine richtige Antwort ist, aber versuchen Sie boost::tie (Teil der Boost :: Tuple-Bibliothek). Es funktioniert auch auf std::pair s.

3

boost::bind wird häufig verwendet, um std :: map-Container für die Verwendung mit Algorithmen anzupassen. Here ist ein Beispiel:

void print_string(const std::string& s) { 
    std::cout << s << '\n'; 
} 


std::map<int,std::string> my_map; 
my_map[0]="Boost"; 
my_map[1]="Bind"; 


std::for_each(my_map.begin(), my_map.end(), 
       boost::bind(&print_string, boost::bind(
       &std::map<int,std::string>::value_type::second,_1))); 
1

Was Kombinationen von verschiedenen Behältern verwendet.

Zum Beispiel, wenn ich einen Vektor in Artikeln partitionieren wollte in einer zusätzlichen Karte enthalten und Elemente, wo nicht in der Zusatzkarte enthalten ist, verwenden ich folgend:

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

Jetzt habe ich ein zweites Problem - während Beim Ausführen der Anwendung kann sich der Status bool von user_info ändern, und später möchte ich den Vektor mit Elementen, die einen Status bool von true haben, neu partitionieren, anstatt nur in der Zusatzkarte enthalten zu sein.

Allerdings habe ich ein Problem beim Zugriff auf das zweite Element eines verschachtelten Paares.

Ich habe Folgendes versucht, aber ich kann nicht scheinen, auf das verschachtelte Paar zuzugreifen!

CActiveUsers::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

Werfen Sie einen Blick auf Boost :: Adapter. Es gibt vordefinierte Adapter zum Iterieren von Map Keys oder Werten, ohne sie in einen Zwischencontainer zu kopieren.

0

Eine Option, die nicht vorgeschlagen wurde, ist std::tr1::get. Siehe Abschnitte 6.1.2 und 6.1.4 von n1745.

std::pair< std::string, int > p("foo", 1729); 

int hr = std::tr1::get<1>(p); 

Auf jeden Fall nicht so einfach wie bind im map Extraktion Fall nutzen, um über die Sie erwähnten, aber immer noch wissenswert. Anpassung von Johannes 'Code:

typedef std::map<std::string, int> map_type; 

std::vector<int> values; // will contain all values 
map_type map; 

// std::tr1::get is overloaded so we need to help the compiler choose 
const map_type::value_type::second_type & (*get)(const map_type::value_type &) = 
    &std::tr1::get< 1, map_type::value_type::first_type, map_type::value_type::second_type >; 

std::transform(map.begin(), 
       map.end(), 
       std::back_inserter(values), 
       get); 
Verwandte Themen