HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMajor

infix_iterator code

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
codeinfix_iteratorstackoverflow

Problem

I've previously posted this on Stack Overflow, and am considering submitting it to Boost for wider distribution, but thought perhaps it would be best to put it up here for peer review first, and see whether there are clear improvements that can be made first.

// infix_iterator.h
// 
#if !defined(INFIX_ITERATOR_H_)
#define  INFIX_ITERATOR_H_
#include 
#include 

template  >

class infix_ostream_iterator :
    public std::iterator
{
    std::basic_ostream *os;
    charT const* delimiter;
    bool first_elem;
public:
    typedef charT char_type;
    typedef traits traits_type;
    typedef std::basic_ostream ostream_type;

    infix_ostream_iterator(ostream_type& s)
        : os(&s),delimiter(0), first_elem(true)
    {}
    infix_ostream_iterator(ostream_type& s, charT const *d)
        : os(&s),delimiter(d), first_elem(true)
    {}
    infix_ostream_iterator& operator=(T const &item)
    {
        // Here's the only real change from ostream_iterator:
        // We don't print the delimiter the first time. After that, 
        // each invocation prints the delimiter *before* the item, not
        // after. As a result, we only get delimiters *between* items,
        // not after every one.
        if (!first_elem && delimiter != 0)
            *os  &operator*() {
        return *this;
    }
    infix_ostream_iterator &operator++() {
        return *this;
    }
    infix_ostream_iterator &operator++(int) {
        return *this;
    }

};

#endif


This is (at least intended to be) pretty much a drop-in replacement for std::ostream_iterator, the sole difference being that (at least in normal use) it only prints out delimiters between items instead of after every item. Code using it looks something like:

#include "infix_iterator.h"

std::vector numbers = {1, 2, 3, 4};

std::copy(begin(numbers), end(numbers), 
          infix_ostream_iterator(std::cout, ", "));


The motivation for this is pretty simple -- with a std::ostream_iterator, your list would co

Solution

Nothing major (just some personal opinion ones):

Consistent Spacing

infix_ostream_iterator(ostream_type& s)
        : os(&s),delimiter(0), first_elem(true)
    {}  //    ^^^ No Space   ^^^Trailing space


Consistent type Naming

// Here we have & on the left
infix_ostream_iterator& operator=(T const &item)

// Here we have it on the right
infix_ostream_iterator &operator*() {


Spelling of delimter

I mistypes it a lot when writing this => delimiter

Easier to read initializer list

Just like I prefer one statement per line, I prefer one variable initialized per line in the initializer list (easier to read).

infix_ostream_iterator(ostream_type& s, charT const *d)
    : os(&s)
    , delimiter(d)
    , first_elem(true)
{}


Remove the if from the main body.

It probably makes no difference to performance, but I would remove the if so the code looks like this:

*os << delimter << item;
delimter = actualDelimter;
return *this;


On construction actualDelimter points at the string provided by the user (or empty string) and delimter is set to point at an empty string.

Code Snippets

infix_ostream_iterator(ostream_type& s)
        : os(&s),delimiter(0), first_elem(true)
    {}  //    ^^^ No Space   ^^^Trailing space
// Here we have & on the left
infix_ostream_iterator<T,charT,traits>& operator=(T const &item)

// Here we have it on the right
infix_ostream_iterator<T,charT,traits> &operator*() {
infix_ostream_iterator(ostream_type& s, charT const *d)
    : os(&s)
    , delimiter(d)
    , first_elem(true)
{}
*os << delimter << item;
delimter = actualDelimter;
return *this;

Context

StackExchange Code Review Q#13176, answer score: 25

Revisions (0)

No revisions yet.