Мне понравилось решение KeithB с бесплатными функциями. Тем не менее, может быть неплохо использовать повторно используемое решение.
Как насчет функциональных объектов, которые обращаются к первому или второму, поскольку вы можете называть экземпляры как угодно:
#include <map>
#include <string>
#include <iostream>
struct GetFirst
{
template <class First, class Second>
First& operator()(std::pair<First, Second>& p)
{
return p.first;
}
template <class First, class Second>
const First& operator()(const std::pair<First, Second>& p)
{
return p.first;
}
};
struct GetSecond
{
template <class First, class Second>
Second& operator()(std::pair<First, Second>& p)
{
return p.second;
}
template <class First, class Second>
const Second& operator()(const std::pair<First, Second>& p)
{
return p.second;
}
};
int main()
{
typedef std::map<std::string, int> Map;
Map persons;
persons["John"] = 20;
persons["Mary"] = 24;
//create named accessors
GetFirst name;
GetSecond age;
for (Map::iterator it = persons.begin(); it != persons.end(); ++it) {
std::cout << name(*it) << " is aging.\n";
++age(*it);
}
for (Map::const_iterator it = persons.begin(); it != persons.end(); ++it) {
std::cout << "Name: " << name(*it) << ", age: " << age(*it) << '\n';
}
}
Это лучшее, что я мог сделать. Я также пытался заставить эти функторы напрямую принимать итератор, но это так или иначе означает, что подпись будет содержать зависимые имена, что, очевидно, делает невозможным вывод типа шаблона (я не смог найти способ перегрузить GetSecond для iterator/const_iterator
даже при тип отложенного возврата C ++ 0x).