equal_range и диапазон для

Обсуждая multimap со своими студентами, я заметил небольшое изменение, которое могло убрать часть шаблона, и мне было интересно, предлагал ли кто-нибудь это комитету по стандартизации, и если да, то каков был ответ.

Канонический метод перебора равного диапазона (взято с cplusplus.com):

// multimap::equal_range
#include <iostream>
#include <map>

int main ()
{
  std::multimap<char,int> mymm;

  mymm.insert(std::pair<char,int>('a',10));
  mymm.insert(std::pair<char,int>('b',20));
  mymm.insert(std::pair<char,int>('b',30));
  mymm.insert(std::pair<char,int>('b',40));
  mymm.insert(std::pair<char,int>('c',50));
  mymm.insert(std::pair<char,int>('c',60));
  mymm.insert(std::pair<char,int>('d',60));

  std::cout << "mymm contains:\n";
  for (char ch='a'; ch<='d'; ch++)
  {
    std::pair <std::multimap<char,int>::iterator,std::multimap<char,int>::iterator> ret;
    ret = mymm.equal_range(ch);
    std::cout << ch << " =>";
    for (std::multimap<char,int>::iterator it=ret.first; it!=ret.second; ++it)
      std::cout << ' ' << it->second;
    std::cout << '\n';
  }

  return 0;
}

В этом случае вы не можете напрямую использовать диапазон, основанный на цикле for, потому что тип возврата equal_range — это pair<multimap<K,V>::iterator, multimap<K,V>::iterator>. Однако простая структура-оболочка должна позволять это:

template <typename T>
struct abstract_collection {
  abstract_collection(pair<T, T> its)
  : m_begin(its.first),
    m_end(its.second) {}
  abstract_collection(T begin, T end)
  : m_begin(begin),
    m_end(end) {}

  T begin() const { return m_begin; }
  T end() const { return m_end; }

  T m_begin;
  T m_end;
};

В сочетании с добавлением функции в multimap (и другие) API для возврата итераторов в этой структуре, а не в паре.

template<typename K, typename V, typename C, typename A>
auto multimap<K, V, C, A>::equal_range_c(K const& k) -> abstract_collection<iterator> {
  return equal_range(k);
}

Или, альтернативно, перегрузка версии std::begin и std::end, которая использует пару итераторов, также должна работать:

template <typename T>
T begin(pair<T, T> p) { return p.first; }

template <typename T>
T end(pair<T, T> p) { return p.second; }

Появлялись ли эти идеи раньше, и если да, то какова была реакция комитета? Они просто неработоспособны или нежелательны по какой-то причине, которую я не вижу?

(Обратите внимание, что код был написан без попыток компилировать или проверять только в демонстрационных целях. Это, вероятно, неправильно. И он не содержит проверки типов, чтобы ограничить итераторы только так, как должно, поскольку это добавило сложности, которая не служила для поясните мысль)


person OmnipotentEntity    schedule 02.05.2016    source источник
comment
Я считаю, что вы ищете библиотеку range-v3, которая/должна быть добавлена ​​в ТС очень скоро. За исключением любых шоу-стопперов, он должен быть включен в C++ в следующей версии после C++17.   -  person NathanOliver    schedule 02.05.2016
comment
Спасибо, это кажется намного более надежным, чем все, что я предлагал, что делает меня счастливым.   -  person OmnipotentEntity    schedule 02.05.2016
comment
Добавление таких перегрузок begin() и end() в пространство имен std является поведением undefined.   -  person Barry    schedule 02.05.2016
comment
Релевантно: stackoverflow.com/q/6167598/2069064   -  person Barry    schedule 02.05.2016


Ответы (1)


Это то, что boost::iterator_range< /a>, который был принят в библиотеку диапазона TS как ranges::iterator_range. Этот TS должен быть включен где-то после C++17.

person Columbo    schedule 02.05.2016