I want to provide a generic line based IO for containers of std::string in a library.
Line based since the strings may contain spaces.
The following code seems to work fine but I’m not sure whether this is the best way to go or whether it creates some ambiguities, I’m failing to grasp.
#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;
}
So the question is: Is this safe and sound ?
You can write the output algorithm using
std::copy():You might use an input iterator for paragraph input, i.e., multiple lines separated by blank lines:
Then you can write the input algorithm using
std::copy()as well:Separating the logic into an iterator type lets you make the input and output algorithms parameterisable, and thus more general. In a template library, that’s typically a good thing. I would avoid adding overloads for standard containers, because you cannot know that they do the right thing on every platform; iterator-based algorithms are more portable, and you don’t have to write all the
template<template<...> class ...>cruft.