C++ std::string的非关联容器的io
我想为库中std::string的容器提供一个基于行的通用IO。 基于行,因为字符串可能包含空格。 下面的代码似乎工作得很好,但我不确定这是否是最好的方法,或者它是否会产生一些歧义,我无法理解C++ std::string的非关联容器的io,c++,string,templates,C++,String,Templates,我想为库中std::string的容器提供一个基于行的通用IO。 基于行,因为字符串可能包含空格。 下面的代码似乎工作得很好,但我不确定这是否是最好的方法,或者它是否会产生一些歧义,我无法理解 #define boostForeach BOOST_FOREACH template< template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container > std::ostr
#define boostForeach BOOST_FOREACH
template< template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container >
std::ostream& operator<< (std::ostream& o, Container<std::string>const & container){
boostForeach(std::string const& str, container) {
o << str << "\n";
}
return o;
}
template< template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container >
std::istream& operator>> (std::istream& in, Container<std::string>& container){
container.clear();
std::string buf;
while(getline(in, buf)) {
if(buf.empty()) break; //stop if empty line found to separate map from other data
container.insert(container.end(),buf);
}
return in;
}
#定义boostForeach BOOST\u FOREACH
模板<模板类容器>
std::ostream&operator(std::istream&in、容器和容器){
容器。清除();
std::字符串buf;
while(getline(in,buf)){
if(buf.empty())break;//如果发现将映射与其他数据分隔开的空行,则停止
container.insert(container.end(),buf);
}
返回;
}
所以问题是:这是否安全可靠?第一个问题是标准容器中模板参数的数量不受标准的约束,这意味着您的代码在任何有额外参数的平台上都会失败 一般来说,我不会为尚未定义的类型提供运算符重载,尤其是对于标准容器。原因是你做不好。特别是,您不能在容器所在的名称空间中声明它们,这意味着ADL不会像魔术一样选择正确的重载。如果您想要一个helper函数,您应该提供一个命名函数,如果需要的话,在这里帮助查找会更简单 试试这个:
#include <iostream>
#include <vector>
#include <string>
template < template<typename,typename> class Container >
std::ostream& operator<<( std::ostream& o, Container<std::string> const & c );
namespace A {
struct S {};
std::ostream& operator<<( std::ostream& o, S const & );
void f() {
std::vector<std::string> v;
std::cout << v;
}
}
int main() {
A::f();
}
#包括
#包括
#包括
模板<模板类容器>
std::ostream&operator第一个问题是标准容器中模板参数的数量不受标准的约束,这意味着您的代码在任何有额外参数的平台上都会失败
一般来说,我不会为尚未定义的类型提供运算符重载,尤其是对于标准容器。原因是你做不好。特别是,您不能在容器所在的名称空间中声明它们,这意味着ADL不会像魔术一样选择正确的重载。如果您想要一个helper函数,您应该提供一个命名函数,如果需要的话,在这里帮助查找会更简单
试试这个:
#include <iostream>
#include <vector>
#include <string>
template < template<typename,typename> class Container >
std::ostream& operator<<( std::ostream& o, Container<std::string> const & c );
namespace A {
struct S {};
std::ostream& operator<<( std::ostream& o, S const & );
void f() {
std::vector<std::string> v;
std::cout << v;
}
}
int main() {
A::f();
}
#包括
#包括
#包括
模板<模板类容器>
std::ostream&operator您可以使用std::copy()
编写输出算法:
将逻辑分离为迭代器类型可以使输入和输出算法参数化,从而更通用。在模板库中,这通常是一件好事。我会避免为标准容器添加重载,因为您无法知道它们在每个平台上都做了正确的事情;基于迭代器的算法更具可移植性,您不必编写所有的模板cruft.您可以使用std::copy()
编写输出算法:
将逻辑分离为迭代器类型可以使输入和输出算法参数化,从而更通用。在模板库中,这通常是一件好事。我会避免为标准容器添加重载,因为您无法知道它们在每个平台上都做了正确的事情;基于迭代器的算法更具可移植性,您不必编写所有的模板cruft.您可能需要。:)@网络编码员:很好!我不知道这件事,一定会试试看你可能想试试。:)@网络编码员:很好!我不知道这一点,肯定会尝试一下,作为反例。你说得很对,我完全忽略了不同名称空间的含义play@Martin:我已看到您的编辑请求。因此,我修改了代码,使其适当地失败。请注意,不需要模板或函数定义,并且在Ideone上不需要模板参数的模板参数名称(默认值也不需要),因为您的代码没有结构,并且相应的运算符仍然失败:prog.cpp:6:错误:模板参数数目错误(1,应该是2)prog.cpp:5:错误:为“模板类容器”提供。std::vector的一个模板参数具有默认值。这就是为什么可能需要完整规范的原因。我添加了模板定义,以便在不存在结构的情况下运行代码。感谢反例。你说得对,我完全忽略了不同名称空间进入时的简化play@Martin:我已看到您的编辑请求。因此,我修改了代码,使其相应地失败。请注意,不需要模板或函数定义,并且模板模板参数的模板参数名称在事件中也不需要(默认值更小)在Ideone上,没有结构的代码和相应的运算符仍然失败:prog.cpp:6:错误:模板参数的数目错误(1,应该是2)prog.cpp:5:错误:为“模板类容器”提供。std::vector的一个模板参数具有默认值。这就是为什么可能需要完整规范的原因。我添加了模板定义,以便在结构不存在时运行代码。
class istream_paragraph_iterator: public std::iterator<std::forward_iterator_tag,std::string>{
std::istream* stream;
std::string line;
public:
istream_paragraph_iterator() : stream(0) {}
istream_paragraph_iterator(std::istream& stream) : stream(&stream) {++*this; //get the first element
}
std::string operator*() const {
return line;
}
const std::string* operator->() const {
return &line;
}
istream_paragraph_iterator& operator++() {
if (stream && (!std::getline(*stream, line) || line.empty()))
stream = 0;
return *this;
}
istream_paragraph_iterator operator++(int) {
istream_paragraph_iterator previous(*this);
++*this;
return previous;
}
bool operator==(const istream_paragraph_iterator& other) const {
return stream == other.stream;
}
bool operator!=(const istream_paragraph_iterator& other) const {
return !(*this == other);
}
};
std::copy(istream_paragraph_iterator(in),
istream_paragraph_iterator(),
std::back_inserter(container));