Topic: add std::map iterators iterator_key_type and iterator_mapped_type
Author: vadima@waterint.com (VAdim)
Date: Tue, 6 Jul 2004 16:35:44 +0000 (UTC) Raw View
> Suggestion:
>
> use boost::transform_iterator with select1st or select2nd.
That really solves problem, thank You.
I think accessing 1st and 2nd elements in the std::map::value type is
to coomon, and desereve special function.
select1st and select2nd are not standard.
And I suggest function:
template< typename Iterator, typename V>
boost::make_transform_iterator( Iterator I, V
Iterator::value_type::*member );
and
template< typename Iterator, typename V>
boost::make_transform_iterator( Iterator I, V
(Iterator::value_type::*f)() );
to ease on fly making iterators
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: vadima@waterint.com (VAdim)
Date: Wed, 30 Jun 2004 23:01:43 +0000 (UTC) Raw View
Motivation:
I wanted to copy mapped values from the map into set, and I did'n find
easy way to do this. Similar problem appears when one want to apply
some function to the second member of the std::map only.
Proposal:
Add bidirectional iterators to the std::map iterator_key_type and
iterator_mapped_type which will point to the first/second part of the
std::map::value_type
Example of implementation:
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
template< typename MapIterator >
class Iter2nd {
MapIterator iter;
public:
typedef typename MapIterator::difference_type difference_type;
typedef typename MapIterator::value_type::second_type value_type;
typedef typename MapIterator::value_type::second_type & reference;
typedef typename MapIterator::value_type::second_type * pointer;
explicit Iter2nd( MapIterator i ) : iter( i ) {}
// Forward iterator requirements
reference operator*() const { return (*iter).second; }
pointer operator->() const { return &(operator*()); }
Iter2nd operator++() { ++iter; return *this; }
Iter2nd operator++(int) { return Iter2nd(iter++); }
// Bidirectional iterator requirements
Iter2nd& operator--() { --iter; return *this; }
Iter2nd operator--(int) { return Iter2nd(iter--); }
// comparisions
bool operator == ( const Iter2nd& rhs ) const { return iter ==
rhs.iter; }
bool operator != ( const Iter2nd& rhs ) const { return iter !=
rhs.iter; }
};
namespace std {
template< class T >
struct iterator_traits< Iter2nd<T> > {
typedef typename Iter2nd<T>::value_type value_type;
typedef typename Iter2nd<T>::difference_type difference_type;
typedef bidirectional_iterator_tag iterator_category;
typedef typename Iter2nd<T>::pointer pointer;
typedef typename Iter2nd<T>::reference reference;
};
}
template< typename MapIterator > Iter2nd<MapIterator>
iter2nd( const MapIterator& iter ) { return Iter2nd<MapIterator>( iter
); }
static void toUpper( std::string & str ) {
std::transform( str.begin(), str.end(), str.begin(), toupper );
};
static std::string toLower( const std::string & str ) {
std::string res;
std::transform( str.begin(), str.end(),
std::back_inserter( res ),
tolower );
return res;
}
int main ( int argc, char * argv[] ) {
std::map<int,std::string> m;
m[1]="one";
m[5]="five";
m[3]="three";
m[7]="five";
// Example 1: for_each on mapped_type
std::for_each( iter2nd( m.begin() ), iter2nd( m.end() ), toUpper );
// Example 1(a): print only mapped_type
std::copy( iter2nd( m.begin() ), iter2nd( m.end() ),
std::ostream_iterator< std::string >( std::cout, " " ));
std::cout << std::endl;
// Example 2: for_each on mapped_type
std::transform( iter2nd( m.begin() ), iter2nd( m.end() ),
iter2nd( m.begin() ),
toLower );
std::copy( iter2nd( m.begin() ), iter2nd( m.end() ),
std::ostream_iterator< std::string >( std::cout, " " ));
std::cout << std::endl;
// create set form mapped_type
std::set< std::string > setstr( iter2nd( m.begin() ), iter2nd(
m.end() ));
std::copy( setstr.begin(), setstr.end(),
std::ostream_iterator< std::string >( std::cout, " " ));
std::cout << std::endl;
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dietmar_kuehl@yahoo.com (Dietmar Kuehl)
Date: Fri, 2 Jul 2004 15:10:10 +0000 (UTC) Raw View
vadima@waterint.com (VAdim) wrote:
> Motivation:
> I wanted to copy mapped values from the map into set, and I did'n find
> easy way to do this. Similar problem appears when one want to apply
> some function to the second member of the std::map only.
>
> Proposal:
> Add bidirectional iterators to the std::map iterator_key_type and
> iterator_mapped_type which will point to the first/second part of the
> std::map::value_type
I would oppose such a proposal: the general approach to do something like
this is the separation of iterators into cursors (the positioning part of
the iterator) and property maps (the property access part of the iterator).
A sample implementation of algorithms based on this is idea is available at
<http://www.dietmar-kuehl.de/cool/cool-20030106.tar.gz>. In addition to
solving the problem you mention, this solves a bunch of other problems, too.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]