$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: Niels Aan de Brugh (nielsadb_at_[hidden])
Date: 2007-12-04 13:15:36
On Mon, Dec 03, 2007 at 03:24:33PM -0800, chun ping wang wrote:
> hmm what do you mean? can you give a example.
>
> template
> <
> class T, class U,
> template <typename ELEM, typename = std::allocator<ELEM> >
> class CONT
> >
> void getKeys(const boost::unordered_map<T, U>& data, const
> CONT<T>::iterator);
There's no need to "templatize" the container. Demanding the iterator is
typedef'ed in the container is a not needed and makes the code less
generic. Rather, just accept all types that model the output iterator
concept and you should be fine, like so (alt.1):
template< typename MapType, typename OutputIterator >
OutputIterator getKeys( MapType const& map, OutputIterator out )
{
for( MapType::const_iterator it = map.begin();
it != map.end(); ++it )
{
*out++ = it->first;
}
return out;
}
This probably works for any type that supports the typical iteration
functions and uses std::pair<>s as iterator values, e.g. std::map<>, but
I haven't compiled or tested the code. Returning the iterator is useful
for the caller: it can immediate call the next function with the
returned iterator without having to determine how many elements you've
written.
This is an example just to show you what I mean in my previous mail. It
would be much better to write an iterator adapter (as suggested
earlier), in which case you can write the above function as a simple
std::copy expression (alt.2):
out = std::copy( my_iterator_adapter( map.begin() ),
my_iterator_adapter( map.end() ), out );
And... you can use all the other STL algorithms (e.g. find_if) directly
on the keys of your map without copying them in a container. This is not
possible using alt.1.
Both of the above alternatives can be used with a function_output_iterator
to create an ad hoc for-all-keys-do-the-following function:
void acceptKey( Key const& key ) { /* ... */ }
// using alt.1
map.getKeys( boost::make_function_output_iterator( acceptKey ) );
// using alt.2
std::copy( my_iterator_adapter( map.begin() ),
my_iterator_adapter( map.end() ),
boost::make_function_output_iterator( acceptKey ) );
Of couse, if you chose alternative 2 you can also use std::for_each,
which is probably a lot clearer to other people reading your code.
There are other uses as well, such as writing to an std::ostream, or
whatever. The STL is quite flexible if you use the right concepts. Note
that all these applications are not possible if you use an STL
container to get the keys.
N.