1

Boost Ranges 是否有内置方法来轻松计算元素,例如用逗号或空格分隔?

我当然知道我可以遍历它们并分别打印它们,但在我看来,这应该以某种方式内置(比如用脚本语言打印矢量)。

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

boost::copy(范围, ostream_iterator(cout, " "))

在我看来很难看。这是惯用语吗?

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

EDIT2:我想做的是:

cout << range;

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

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

或者可能使用范围适配器。

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

2 回答 2

4

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

就个人而言,我刚刚习惯了使用std::copy. 对于这类事情,aninfix_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<<需要一个向量,但是让它取一个范围相对来说是微不足道的。

于 2012-04-04T16:57:48.890 回答
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); }

该函数返回一个字符串,它应该采用任何向前可迭代的范围,例如列表、向量、集合等,其中每个元素的取消引用可以由 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() 名称可能会与某些命名空间发生冲突,因此您可能希望将名称更改为类似的名称,例如加入或联合。此外,如果您曾经使用过 boost,您可能希望使用 boost::begin(r) 而不是 r.begin() 以获得更好的兼容性。

于 2012-04-04T19:41:40.180 回答