首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >infix_iterator代码

infix_iterator代码
EN

Code Review用户
提问于 2012-06-29 05:32:19
回答 6查看 3.4K关注 0票数 71

我以前曾在Stack Overflow上发布过这篇文章,并且正在考虑提交它以促进更广泛的发行,但我认为最好先把它放在这里进行同行评审,看看是否可以首先进行明显的改进。

代码语言:javascript
复制
// infix_iterator.h
// 
#if !defined(INFIX_ITERATOR_H_)
#define  INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>

template <class T,
          class charT=char,
          class traits=std::char_traits<charT> >

class infix_ostream_iterator :
    public std::iterator<std::output_iterator_tag,void,void,void,void>
{
    std::basic_ostream<charT,traits> *os;
    charT const* delimiter;
    bool first_elem;
public:
    typedef charT char_type;
    typedef traits traits_type;
    typedef std::basic_ostream<charT,traits> 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<T,charT,traits>& 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 << delimiter;
        *os << item;
        first_elem = false;
        return *this;
    }

    infix_ostream_iterator<T,charT,traits> &operator*() {
        return *this;
    }
    infix_ostream_iterator<T,charT,traits> &operator++() {
        return *this;
    }
    infix_ostream_iterator<T,charT,traits> &operator++(int) {
        return *this;
    }

};

#endif 

这在很大程度上是std::ostream_iterator的替代,唯一的区别是(至少在正常使用中)它只在项之间打印分隔符,而不是在每个项之后。使用它的代码如下所示:

代码语言:javascript
复制
#include "infix_iterator.h"

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

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

这样做的动机很简单--在std::ostream_iterator中,您的列表会像1, 2, 3, 4,一样显示出来,但是在infix_iterator中,它会以1, 2, 3, 4的形式出现。

顺便提一句,虽然我在这个演示代码中使用了一些C++11特性,但我认为迭代器本身对C++03应该没问题--不过如果有人发现没有C++11支持的编译器有什么问题,我也想听听。

编辑:如果有人关心,这是包含来自@Konrad和@Loki的输入的新版本。多亏了你们俩。

代码语言:javascript
复制
// infix_iterator.h
#if !defined(INFIX_ITERATOR_H_)
#define  INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>
#include <string>

template <class T, class charT=char, class traits=std::char_traits<charT> >
class infix_ostream_iterator :
    public std::iterator<std::output_iterator_tag, void, void, void, void>
{
    std::basic_ostream<charT,traits> *os;
    std::basic_string<charT> delimiter;
    std::basic_string<charT> real_delim;

public:

    typedef charT char_type;
    typedef traits traits_type;
    typedef std::basic_ostream<charT, traits> ostream_type;

    infix_ostream_iterator(ostream_type &s)
        : os(&s)
    {}

    infix_ostream_iterator(ostream_type &s, charT const *d)
        : os(&s), 
          real_delim(d)
    {}

    infix_ostream_iterator<T, charT, traits> &operator=(T const &item)
    {
        *os << delimiter << item;
        delimiter = real_delim;
        return *this;
    }

    infix_ostream_iterator<T, charT, traits> &operator*() {
        return *this;
    }

    infix_ostream_iterator<T, charT, traits> &operator++() {
        return *this;
    }

    infix_ostream_iterator<T, charT, traits> &operator++(int) {
        return *this;
    }
};

#endif 
EN

回答 6

Code Review用户

回答已采纳

发布于 2012-06-29 23:41:36

没什么大不了的(只是一些个人意见):

一致间距

代码语言:javascript
复制
    infix_ostream_iterator(ostream_type& s)
        : os(&s),delimiter(0), first_elem(true)
    {}  //    ^^^ No Space   ^^^Trailing space

一致类型命名

代码语言:javascript
复制
// 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*() {

拼写delimter

我在写这个=> delimiter时经常出错。

易于读取初始化程序列表

就像我喜欢每行一条语句一样,我更喜欢初始化程序列表中每行初始化一个变量(更容易阅读)。

代码语言:javascript
复制
infix_ostream_iterator(ostream_type& s, charT const *d)
    : os(&s)
    , delimiter(d)
    , first_elem(true)
{}

从主体.

中删除if

这可能对性能没有什么影响,但我会删除if,因此代码如下所示:

代码语言:javascript
复制
*os << delimter << item;
delimter = actualDelimter;
return *this;

在构造时,actualDelimter指向用户提供的字符串(或空字符串),delimter设置为指向空字符串。

票数 25
EN

Code Review用户

发布于 2012-06-29 12:07:53

我在代码中唯一能批评的是,infix操作符和指针/引用声明之间的空格位置不一致。

代码语言:javascript
复制
class charT=char,
public std::iterator<std::output_iterator_tag,void,void,void,void>

…等等,缺了空间。

代码语言:javascript
复制
: os(&s),delimiter(0), first_elem(true)

…等,空间的使用不一致。

代码语言:javascript
复制
infix_ostream_iterator<T,charT,traits>& operator=(T const &item)
infix_ostream_iterator<T,charT,traits> &operator*() {

…等等,&的位置不一致。

我还将统一使用函数定义之间的空行,并删除template <…>块和类头之间以及类定义末尾的空行。

吹毛求疵,当然,但这是唯一的批评。

票数 15
EN

Code Review用户

发布于 2012-07-21 18:23:03

我还声明第一个构造函数为显式构造函数:

代码语言:javascript
复制
explicit infix_ostream_iterator(ostream_type &s)
        : os(&s)
    {}

虽然我可以想象这种迭代器的使用是相当有限的,但是这样您就可以确保不会发生不必要的类型转换。

票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/13176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档