tipos lenguaje funciones estructuras ejemplos datos comandos codigos caracteristicas c++ foreach c++11 range std-pair

funciones - lenguaje c++ ejemplos



¿Por qué se eliminó el acceso al rango de pares de C++ 11? (3)

Creo que el documento de 2009 "Pares no hacen buenos rangos" de Alisdair Meredith es al menos parte de la respuesta. Básicamente, muchos algoritmos devuelven pares de iteradores que en realidad no se garantiza que sean rangos válidos. Parece que eliminaron el soporte para pair<iterator,iterator> del bucle for-range por este motivo. Sin embargo, la solución propuesta no se ha adoptado completamente.

Si sabe con certeza que algún par de iteradores realmente representa un rango válido, entonces podría envolverlos en un tipo personalizado que ofrezca funciones de miembro de inicio () / end ():

template<class Iter> struct iter_pair_range : std::pair<Iter,Iter> { iter_pair_range(std::pair<Iter,Iter> const& x) : std::pair<Iter,Iter>(x) {} Iter begin() const {return this->first;} Iter end() const {return this->second;} }; template<class Iter> inline iter_pair_range<Iter> as_range(std::pair<Iter,Iter> const& x) { return iter_pair_range<Iter>(x); } int main() { multimap<int,int> mm; ... for (auto& p : as_range(mm.equal_range(42))) { ... } }

(no probado)

Estoy de acuerdo, esto es un poco verrugoso. Las funciones que devuelven rangos válidos (como equal_range) deberían decirlo utilizando un tipo de devolución apropiado. Es un poco embarazoso que tengamos que confirmarlo manualmente a través de algo como as_range anterior.

Acabo de descubrir que, en un momento, el borrador de C ++ 11 tenía std::begin / std::end overloads para std::pair que permitía tratar un par de iteradores como un rango adecuado para su uso en un bucle for basado en rangos (N3126, sección 20.3.5.5), pero esto se ha eliminado desde entonces.

¿Alguien sabe por qué fue eliminado?

Encuentro la eliminación muy desafortunada, porque parece que no hay otra manera de tratar un par de iteradores como un rango. En efecto:

  • Las reglas de búsqueda para comenzar / finalizar en un bucle for basado en rango dicen que begin / end se buscan en 1) como funciones miembro del objeto range 2) como funciones gratuitas en "espacios de nombres asociados"
  • std::pair no tiene funciones de miembro de comienzo / fin
  • El único espacio de nombres asociado para std::pair<T, U> en general es el espacio de nombres estándar
  • No podemos sobrecargar std::begin / std::end para std::pair nosotros mismos
  • No podemos especializar std::begin / std::end para std::pair (porque la especialización debería ser parcial y no está permitida para funciones)

¿Hay alguna otra forma en la que me estoy perdiendo?


Puedes usar boost::make_iterator_range . Construye un iterator_range con los métodos begin() y end() . boost::make_iterator_range puede aceptar std::pair de iteradores.


ampliando la respuesta anterior utilizando optimizaciones de c ++ 11:

#include <utility> template<class Iter> struct range_t : public std::pair<Iter, Iter> { using pair_t = std::pair<Iter, Iter>; range_t(pair_t&& src) : std::pair<Iter, Iter>(std::forward<pair_t>(src)) {} using std::pair<Iter, Iter>::first; using std::pair<Iter, Iter>::second; Iter begin() const { return first; } Iter end() const { return second; } }; template<class Iter> range_t<Iter> range(std::pair<Iter, Iter> p) { return range_t<Iter>(std::move(p)); } template<class Iter> range_t<Iter> range(Iter i1, Iter i2) { return range_t<Iter>(std::make_pair(std::move(i1), std::move(i2))); } // TEST: #include <iostream> #include <set> using namespace std; int main() { multiset<int> mySet { 6,4,5,5,5,3,3,67,8,89,7,5,45,4,3 }; cout << "similar elements: "; for (const auto&i : range(mySet.lower_bound(5), mySet.upper_bound(10))) { cout << i << ","; } cout << "/n"; int count = 0, sum = 0; for (const auto& i: range(mySet.equal_range(5))) { ++count; sum += i; } cout << "5 appears " << count << " times/n" << "the sum is " << sum << "/n"; return 0; }