Victor,
I've implemented the following, and tested it with ofstream, and char
delimiters. It works quite nicely. As you can see it is parameterized on the
stream type, iterator type and three delimiter types. The latter allows
using non-char delimiters of mixed type, as long as operator<< is defined
for each. Currently all args are copied, I'm not sure if this will be a
limitation, but for my usage it is fine. I've used iterators rather than a
container reference, because my second application of this facility was with
a container of shared_ptr<T>. I was able to use Dave Abrahams
boost::indirect_iterator_generator to be able to access the stored T's. See
the example usage below.
I also have the vague feeling this could be implemented leveraging
boost::function. This is a pretty small but useful utility IMHO. If there is
interest in boostification, it should probably be part of one of the
existing libraries. It's kind of an inverse tokenizer/parser of sorts.
Another question I have is: Is there a problem with parameter "class
tStream" versus the elaborated std::basic_ostream
class range_streamer { tItr mBeg; tItr mEnd; tDBeg mDBeg; tDInner mDInner; tDEnd mDEnd; public: range_streamer ( tItr aBeg , tItr aEnd , tDBeg aDBeg , tDInner aDInner , tDEnd aDEnd ) : mBeg ( aBeg ) , mEnd ( aEnd ) , mDBeg ( aDBeg ) , mDInner( aDInner ) , mDEnd ( aDEnd ) {} template< class tStream > void OutputTo( tStream& s )const { if( mbeg != mEnd ) { tItr lItr = mBeg; s << mDBeg << *lItr; for( ++lItr ; lItr != mEnd ; ++lItr ) { s << mDInner << *lItr; } s << mDEnd; } } }; template < class tItr , class tDBeg , class tDInner , class tDEnd
inline range_streamer
inline tStream& operator<<
( tStream& s
, const range_streamer
is this what you had in mind?? I've considered this from time to time (first time I've formalized it tho) especially thinking of alternatives to the 3 delimiter arguments (substitute one? "{,}" ??) or what-have-you maybe we should boostify it?
template <typename InputItr> ostream& range_streamer(ostream& to, InputItr start, InputItr stop, const char* sdelim, const char* mdelim, const char* edelim) { // output the beginning delimiter to << sdelim;
// output the 1st element if it exists if (start != stop) to << *start++;
// output the rest of the list (if any) separated by mdelim while (start != stop) { to << mdelim << *start; ++start; } //output the ending delimiter and return return to << edelim; } and of course, if you're going to do it, do it all the way: template <typename Container> inline ostream& container_streamer(ostream& to, Container const& cont, const char* sdelim, const char* mdelim, const char* edelim) {return range_streamer(to, cont.begin(), cont.end(), sdelim, mdelim, edelim);}
At Wednesday 2003-09-03 09:07, you wrote:
Before rolling my own, does boost have a facility to stream out an iterator range without the dangling delimiter at the end? For example
std::ostream& operator<<( std::ostream& s, const MyClass& aC ) { const std::string lDelim( "," );
std::vector<int> lInts;
lInts.push_back(1); lInts.push_back(2); lInts.push_back(3);
std::ostream_iterator<int> lItr( s, lDelim.c_str() );
std::copy( lInts.begin(), lInts.end(), lItr ); }
yields:
1,2,3,
I'm thinking something like the following usage would be nice:
s << range_streamer( lInts.begin(), lInts.end(), "{", "," "}" );
yielding:
{1,2,3}
Any thoughts?
--
Jeff Flinn Applied Dynamics, International
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users