Существует ли стандартный функциональный объект C ++ для разделения std :: pair? - PullRequest
10 голосов
/ 17 декабря 2008

Кто-нибудь знает, существует ли де-факто стандартный (т.е. TR1 или Boost) функциональный объект C ++ для доступа к элементам std :: pair? Дважды за последние 24 часа мне хотелось, чтобы у меня было что-то вроде функции keys для хэшей Perl. Например, было бы неплохо запустить std :: transform для объекта std :: map и сбросить все ключи (или значения) в другой контейнер. Я, конечно, мог бы написать такой функциональный объект, но я бы предпочел повторно использовать то, на чем было много глазных яблок.

Ответы [ 6 ]

17 голосов
/ 17 декабря 2008

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));
4 голосов
/ 17 декабря 2008

Судя по тому, как вы сформулировали свой вопрос, я не уверен, что это правильный ответ, но попробуйте boost::tie (часть библиотеки Boost :: tuple). Работает и на std::pair с.

3 голосов
/ 17 декабря 2008

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)));
1 голос
/ 17 ноября 2011

Посмотрите на boost :: adapters. Существуют предопределенные адаптеры для перебора ключей или значений карты без их копирования в промежуточный контейнер.

1 голос
/ 21 сентября 2009

Как насчет использования комбинаций разных контейнеров.

Например, когда я хотел разделить вектор на элементы, содержащиеся в дополнительной карте, и элементы, которые не были включены в дополнительную карту, я использовал следующее:

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); 
0 голосов
/ 18 ноября 2011

Один вариант, который не был предложен, - 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);
...