cout一个boost ::元素范围

时间:2012-04-04 16:53:17

标签: c++ boost boost-range

Boost Ranges是否有一种内置方式可以轻松地播放元素,例如用逗号或空格分隔?

我当然知道我可以循环遍历它们并单独打印它们,但在我看来,这应该以某种方式构建(比如在脚本语言中打印矢量)。

在我看到的示例程序中,作者将范围复制到cout:

  

boost :: copy(range,ostream_iterator(cout,“”))

对我来说很难看。这是惯用的吗?

编辑:std迭代器的解决方案也是可以接受的。

EDIT2: 我想做的是:

cout << range;

但我认为不行。 所以我希望的是这样的(Python启发):

cout << range.join(", ");

或者使用范围适配器。

cout << (range | stringify(", "));

2 个答案:

答案 0 :(得分:4)

我不相信它曾经真正完成/抛光,但这是Boost.Explore的意图。

就个人而言,我已经习惯使用std::copy。对于这种事情,infix_ostream_iterator有时会非常有用。例如,像这样:

#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include "infix_iterator.h"

template <typename T>
std::ostream& operator<<(std::ostream &o, const std::vector<T>& v) { 
    o << "[";
    std::copy(v.begin(), v.end(), infix_ostream_iterator<T>(o, ", ")); 
    o << "]";
    return o; 
}

int main() { 

    std::vector<int> x;

    for (int i=0; i<20; i+=2)
        x.push_back(i);

    std::cout << x << "\n";
    return 0;
}

按照目前的情况,这会有operator<<取一个向量,但是让它取一个范围会相对微不足道。

答案 1 :(得分:1)

您可能希望定义一个通用函数来输出正向可迭代范围。这是我使用的join()函数:

template<typename ForwardIter>
std::string join(const ForwardIter& it1, const ForwardIter& it2, const std::string& separator=" ") {
    if(it1 != it2) {
        std::ostringstream s;
        s << *it1;
        for(ForwardIter i=it1+1; i!=it2; i++)  s << separator << *i;
        return s.str();
    }
    else return "";
}

template<typename Range>
std::string join(const Range& r, const std::string& separator=" ") { return join(r.begin(), r.end(), separator); }

此函数返回一个字符串,它应该采用任何前向可迭代范围,例如list,vector,set等,其中每个元素的取消引用可以由ostream单独输出。使用此功能,您可以使用它:

list<int> a = {1,2,3,4};
set<int> b = {4,3,2,1};
vector<int> c = {1,2,3,4};


cout << join(a) << endl;
cout << join(b, ",") << endl;
cout << join(c.begin(), c.begin()+2, "~") << endl;

我记得join()名称可能会与某个名称空间冲突,因此您可能希望将名称更改为类似的名称,例如join或joint。此外,如果您使用boost,您可能需要使用boost :: begin(r)而不是r.begin()以获得更好的兼容性。

相关问题