stl

Passing extra arguments to output operator

I usually implement the output operator for a class, operator<<().
I find it useful for debugging and regression testing purposes.
Occasionally when defining a class hierarchy with polymorphism in mind
I’ll instead define a virtual print() method.

Base  base;
std::cout < < "base = " << base << std::endl;

Here's the typical implementation:
Continue reading...

Switching keys in values in a map

A functor that reverses a pair: first becomes second,
second becomes first. Useful for switching
from a map to another map (or multimap in this example) where
the value becomes the key and the key the value.

std::map m;
std::multimap m2;
m["a"] = 0;
m["b"] = 1;
m["c"] = 0;
std::transform (m.begin(), m.end(), std::inserter (m2, m2.begin()),
                pair_switch::value_type> ());

And the actual code:

template
struct pair_switcher : public std::unary_function >
{
    typedef std::pair result_type;
    typedef PairType argument_type;
    result_type operator()(const argument_type &p) const
    {
        return result_type (p.second, p.first);
    }
};

Functor for deleting objects

In a destructor for a class, I had a std::vector of pointers that I wanted to delete. I started to write the usual for(;;) loop and realized I do this often enough I should make it easy to use std::for_each().
Here’s the functor (based on std::unary_function):

template
struct deleter: public std::unary_function
{
    bool operator()(Type * ptr) const
    {
        delete ptr;
        return true;
    }
};

And here’s some sample code using it:

std::vector m_symbols;
// ...
std::for_each (m_symbols.begin(), m_symbols.end(), deleter());

I added a return of true because some other template code wasn’t happy about “return void” — supposedly something fixed in recent compilers.

A better output_iterator

I was using the std::stream_iterator, for example:

    std::vector    vals;
    vals.push_back (12);
    vals.push_back (22);
    vals.push_back (5);
    vals.push_back (30);
    // The std::ostream_iterator appends the ","
    std::ostringstream  str3;
    std::copy (vals.begin(), vals.end(), std::ostream_iterator (str3, ","));
    CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30,"), str3.str());

It has the “,” after the last item.
So here’s an implementation that doesn’t append the seperator after the last one:

#ifndef INCLUDED_OUTITER_H
#define INCLUDED_OUTITER_H
#include 
/**
 * A replacement for std::ostream_iterator that doesn't put the
 * seperator after the last item.
 */
template >
class outiter : public std::iterator
{
public:
    typedef CharType            char_type;
    typedef Traits          traits_type;
    typedef std::basic_ostream    ostream_type;
    /// Initialize from a stream
    outiter (ostream_type &stream)
    : m_stream (&stream),
      m_string (0),
      m_started (false)
    {}
    /// Copy constructor
    outiter (const outiter ©)
    : m_stream (copy.m_stream),
      m_string (copy.m_string),
      m_started (copy.m_started)
    {}
    /// Initialize from a stream and the seperator
    outiter (ostream_type &stream, const CharType *str)
    : m_stream (&stream),
      m_string (str),
      m_started (false)
    {}
    /// Assignment actually does the output
    outiter &
    operator=(const Type &value)
    {
    if (!m_started)
    {
        m_started = true;
    }
    else if (m_string)
    {
            (*m_stream) << m_string;
    }
    (*m_stream) << value;
    return *this;
    }
    /// Just return a reference to this
    outiter &
    operator*()
    {
    return *this;
    }
    /// Just return a reference to this
    outiter &
    operator++()
    {
    return *this;
    }
    /// Just return a reference to this
    outiter &
    operator++(int)
    {
    return *this;
    }
private:
    /// The stream to write to
    ostream_type *      m_stream;
    /// The seperator (may be NULL)
    const char_type *       m_string;
    /// Flag to indicate if we've output anything
    bool            m_started;
};
#endif /* INCLUDED_OUTITER_H */

And here's the corresponding code to use it:

    std::ostringstream  str;
    std::copy (vals.begin(), vals.end(), outiter (str, ","));
    CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30"), str.str());

Copying a std::vector into a std::map

I had two vector’s with the first being the keys and the second being the values. It took a couple tries before I got the STL working for me!
The first thing was to check if the std::map constructors had something useful. It certainly seems like taking two sets of iterators would be a great way to initialize a map. No such luck.
So how about one of the std algorithms to copy the keys and values into the map? std::copy seemed likely but it only takes a single sequence. A little more digging and std::transform. The second version of std::transform takes two sequences, an output iterator, and a binary function to convert the two values from the two sequences into something that can be inserted into the output iterator. Perfect.
So how to turn the two values into a pair suitable for std::map? The std::make_pair
is exactly what is needed. The hard part is getting the syntax so you can pass it as a function: make_pair in this example.
So the code finally looks like:

#include 
#include 
#include 
#include 
#include 
#include 
void test()
{
    std::map  m;
    std::vector    keys;
    std::vector        values;
    std::transform (keys.begin(), keys.end(),
                    values.begin(),
                    std::inserter (m, m.begin()),
                    std::make_pair);
}