Boost Ranges是否有一种内置方式可以轻松地播放元素,例如用逗号或空格分隔?
我当然知道我可以循环遍历它们并单独打印它们,但在我看来,这应该以某种方式构建(比如在脚本语言中打印矢量)。
在我看到的示例程序中,作者将范围复制到cout:
boost :: copy(range,ostream_iterator(cout,“”))
对我来说很难看。这是惯用的吗?
编辑:std迭代器的解决方案也是可以接受的。
EDIT2: 我想做的是:
cout << range;
但我认为不行。 所以我希望的是这样的(Python启发):
cout << range.join(", ");
或者使用范围适配器。
cout << (range | stringify(", "));
答案 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()以获得更好的兼容性。