Кто-нибудь знает, есть ли функциональный объект де-факто (т.е. TR1 или Boost) С++ для доступа к элементам std:: pair? Дважды за последние 24 часа я хотел, чтобы у меня было что-то вроде функции keys
для хэшей Perl. Например, было бы неплохо запустить std:: transform на объекте std:: map и сбросить все ключи (или значения) в другой контейнер. Я мог бы, конечно, написать такой функциональный объект, но я бы предпочел повторное использование чего-то, на котором было много глазных яблок.
Существует ли стандартный объект С++ для разделения пары std:: pair?
Ответ 1
boost::bind
- это то, что вы ищете.
boost::bind(&std::pair::second, _1); // returns the value of a pair
Пример:
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));
Ответ 2
Из того, как вы сформулировали свой вопрос, я не уверен, что это правильный ответ, но попробуйте boost::tie
(часть библиотеки Boost:: tuple). Он работает и с std::pair
.
Ответ 3
boost:: bind часто используется для адаптации контейнеров std:: map для использования с алгоритмами. Здесь приведен пример:
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)));
Ответ 4
Как использовать комбинации разных контейнеров.
Например, когда я хотел разбить вектор на элементы, содержащиеся в дополнительной карте и элементах, где не содержится в дополнительной карте, я использовал следующее:
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()));
Теперь у меня есть вторая проблема - во время запуска приложения статус bool user_info может измениться, а затем я хочу переразделить вектор с элементами, которые имеют статус bool true, а не просто содержатся в дополнительная карта.
Однако у меня, похоже, проблема с доступом к второму элементу вложенной пары.
Я попробовал следующее, но я не могу получить доступ к вложенной паре!
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);
Ответ 5
Взгляните на boost:: adapters. Существуют предопределенные адаптеры для итерации над ключами карты или значениями без копирования их в промежуточный контейнер.
Ответ 6
Один вариант, который не был предложен, - std::tr1::get
. См. Разделы 6.1.2 и 6.1.4 n1745.
std::pair< std::string, int > p( "foo", 1729 );
int hr = std::tr1::get< 1 >( p );
Определенно не так просто использовать как bind
в случае извлечения map
, о котором вы упомянули, но по-прежнему стоит знать. Адаптация кода Йоханнеса:
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);