- вы не можете перегрузить оператор [] как не член
- вы не можете определить функцию-член, которая не была объявлена в определении класса
- вы не можете изменить определение классаиз std :: pair
Вот реализация, не являющаяся членом:
/// @return the nth element in the pair. n must be 0 or 1.
template <class T>
const T& pair_at(const std::pair<T, T>& p, unsigned int n)
{
assert(n == 0 || n == 1 && "Pair index must be 0 or 1!");
return n == 0 ? p.first: p.second;
}
/// @return the nth element in the pair. n must be 0 or 1.
template <class T>
T& pair_at(std::pair<T, T>& p, unsigned int index)
{
assert(index == 0 || index == 1 && "Pair index must be 0 or 1!");
return index == 0 ? p.first: p.second;
}
// usage:
pair<int, int> my_pair(1, 2);
for (int j=0; j < 2; ++j)
++pair_at(my_pair, j);
Обратите внимание, что нам нужны две версии: одна для пар только для чтения и одна для изменяемых пар.
Не бойтесь свободно использовать функции, не являющиеся членами.Как сказал сам Страуструп, нет необходимости моделировать все с помощью объекта или дополнять все путем наследования.Если вы хотите использовать классы, предпочтите композицию наследованию.
Вы также можете сделать что-то вроде этого:
/// Applies func to p.first and p.second.
template <class T, class Func>
void for_each_pair(const std::pair<T, T>& p, Func func)
{
func(p.first);
func(p.second);
}
/// Applies func to p.first and p.second.
template <class T, class Func>
void for_each_pair(std::pair<T, T>& p, Func func)
{
func(p.first);
func(p.second);
}
// usage:
pair<int, int> my_pair(1, 2);
for_each_pair(my_pair, [&](int& x){
++x;
});
Это не слишком громоздко для использования, если у вас есть C ++11 лямбд и, по крайней мере, немного безопаснее, так как он не имеет возможности выходить за пределы.