que patron libreria iteradores iterador español ejemplos ejemplo diseño c++ maps iterator adapter

c++ - patron - que es un iterador en java



adaptador iterador para iterar solo los valores en un mapa? (4)

Acabo de volver a C ++ después de un par de años de hacer mucho C # y recientemente Objective C.

Una cosa que he hecho antes es rodar mi propio adaptador de iterador para std :: map que se eliminará solo a la parte de valor, en lugar del par de clave-valor. Esto es algo bastante común y natural de hacer. C # proporciona a esta instalación las propiedades de Claves y Valores de su clase de Diccionario. Objective-C''s NSDictionary, de manera similar, tiene allKeys y allValues.

Desde que estuve "lejos", Boost adquirió las bibliotecas Range y ForEach, que ahora utilizo ampliamente. Me preguntaba si entre los dos había alguna facilidad para hacer lo mismo, pero no he podido encontrar nada.

Estoy pensando en hacer algo con los adaptadores de iteración de Boost, pero antes de seguir por esa ruta, pensé que podría preguntar aquí si alguien sabe de una instalación de este tipo en Boost, o en otro lugar preparado.


No creo que haya nada fuera de lo normal. Puedes usar boost :: make_transform.

template<typename T1, typename T2> T2& take_second(const std::pair<T1, T2> &a_pair) { return a_pair.second; } void run_map_value() { map<int,string> a_map; a_map[0] = "zero"; a_map[1] = "one"; a_map[2] = "two"; copy( boost::make_transform_iterator(a_map.begin(), take_second<int, string>), boost::make_transform_iterator(a_map.end(), take_second<int, string>), ostream_iterator<string>(cout, "/n") ); }


Continuando con la respuesta de David, hay otra posibilidad de poner el problema al crear una clase derivada de boost :: transform_iterator. Estoy usando esta solución en mis proyectos:

namespace detail { template<bool IsConst, bool IsVolatile, typename T> struct add_cv_if_c { typedef T type; }; template<typename T> struct add_cv_if_c<true, false, T> { typedef const T type; }; template<typename T> struct add_cv_if_c<false, true, T> { typedef volatile T type; }; template<typename T> struct add_cv_if_c<true, true, T> { typedef const volatile T type; }; template<typename TestConst, typename TestVolatile, typename T> struct add_cv_if: public add_cv_if_c<TestConst::value, TestVolatile::value, T> {}; } // namespace detail /** An unary function that accesses the member of class T specified in the MemberPtr template parameter. The cv-qualification of T is preserved for MemberType */ template<typename T, typename MemberType, MemberType T::*MemberPtr> struct access_member_f { // preserve cv-qualification of T for T::second_type typedef typename detail::add_cv_if< std::tr1::is_const<T>, std::tr1::is_volatile<T>, MemberType >::type& result_type; result_type operator ()(T& t) const { return t.*MemberPtr; } }; /** @short An iterator adaptor accessing the member called ''second'' of the class the iterator is pointing to. */ template<typename Iterator> class accessing_second_iterator: public boost::transform_iterator< access_member_f< // note: we use the Iterator''s reference because this type // is the cv-qualified iterated type (as opposed to value_type). // We want to preserve the cv-qualification because the iterator // might be a const_iterator e.g. iterating a const // std::pair<> but std::pair<>::second_type isn''t automatically // const just because the pair is const - access_member_f is // preserving the cv-qualification, otherwise compiler errors will // be the result typename std::tr1::remove_reference< typename std::iterator_traits<Iterator>::reference >::type, typename std::iterator_traits<Iterator>::value_type::second_type, &std::iterator_traits<Iterator>::value_type::second >, Iterator > { typedef boost::transform_iterator< access_member_f< typename std::tr1::remove_reference< typename std::iterator_traits<Iterator>::reference >::type, typename std::iterator_traits<Iterator>::value_type::second_type, &std::iterator_traits<Iterator>::value_type::second >, Iterator > baseclass; public: accessing_second_iterator(): baseclass() {} // note: allow implicit conversion from Iterator accessing_second_iterator(Iterator it): baseclass(it) {} };

Esto lleva a un código aún más limpio:

void run_map_value() { typedef map<int, string> a_map_t; a_map_t a_map; a_map[0] = "zero"; a_map[1] = "one"; a_map[2] = "two"; typedef accessing_second_iterator<a_map_t::const_iterator> ia_t; // note: specify the iterator adaptor type explicitly as template type, enabling // implicit conversion from begin()/end() copy<ia_t>(a_map.begin(), a_map.end(), ostream_iterator<string>(cout, "/n") ); }



Hay un adaptador de rango de impulso para exactamente este propósito. Ver http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html

(Este ejemplo descifrado desde allí)

int main(int argc, const char* argv[]) { using namespace boost::assign; using namespace boost::adaptors; std::map<int,int> input; for (int i = 0; i < 10; ++i) input.insert(std::make_pair(i, i * 10)); boost::copy( input | map_values, std::ostream_iterator<int>(std::cout, ",")); return 0; }