Boost logo

Boost Users :

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.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net