富豪的ostream_iterator

id:yotto-k:20060424 さんのindexed_rangeじゃなくて、その出力結果について。

0.3, 0.7, 0.6, 0.2, 0.9, 0.2, 0.7, 0, 0.3, 0.4, 

最後の", "が気になりませんか?
yotto-kさんの例だとlambdaを使っていますが、ostream_iteratorでも結果は同じです。
この仕様のため、ostream_iteratorはデリミタが改行以外の場合いまいち使えません。
要は2回目以降の出力の際、要素の前にデリミタを出力すればよいのですが、反復子はアルゴリズム中で予測不可能なコピーをされるため、出力回数を単純に反復子に持たせてしまうとカウントがずれてしまうことがあります。

で、少しメモリがもったいないですが、shared_ptrにフラグを入れてやってみました。

#include <boost/shared_ptr.hpp>
#include <iosfwd>
#include <iterator>

namespace hamigaki
{

template <class T, class CharT=char, class Traits=std::char_traits<CharT> >
class ostream_iterator :
    public std::iterator<std::output_iterator_tag,void,void,void,void>
{
public:
    typedef CharT char_type;
    typedef Traits traits_type;
    typedef std::basic_ostream<CharT,Traits> ostream_type;

    ostream_iterator(ostream_type& s) : out_stream(&s), delim(0)
    {
    }

    ostream_iterator(ostream_type& s, const CharT* delimiter)
        : out_stream(&s), delim(delimiter), is_first(new bool(true))
    {
    }

    ostream_iterator<T,CharT,Traits>& operator=(const T& value)
    {
        if (delim)
        {
            if (*is_first)
                *is_first = false;
            else
                *out_stream << delim;
        }
        *out_stream << value;

        return *this;
    }

    ostream_iterator<T,CharT,Traits>& operator*()
    {
        return *this;
    }

    ostream_iterator<T,CharT,Traits>& operator++()
    {
        return *this;
    }

    ostream_iterator<T,CharT,Traits>& operator++(int)
    {
        return *this;
    }

private:
    ostream_type* out_stream;
    const CharT* delim;
    boost::shared_ptr<bool> is_first;
};

} // namespace hamigaki

最初、function_output_iteratorで実装したんですが、かえってコードが長くなったのでやめました。
std::ostream_iteratorと混同するので、名前は変えたほうがいいかもしれません。

#なんか勘違いしてた気がする。述語じゃないのでshared_ptrに入れなくていいかも。
#厳密にはshared_ptrが必要。SGIの定義に従うなら不要。