|
Boost Users : |
From: Jeff Flinn (TriumphSprint2000_at_[hidden])
Date: 2003-09-05 07:09:09
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<charT,traits> approach as
in Josuttis?
-----------range_streamer.hpp-------------------
template
< class tItr
, class tDBeg
, class tDInner
, class tDEnd
>
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<tItr,tDBeg,tDInner,tDEnd>
range_stream
( tItr aBeg
, tItr aEnd
, tDBeg aDBeg
, tDInner aDInner
, tDEnd aDEnd
)
{
typedef range_streamer<tItr,tDBeg,tDInner,tDEnd> tRS;
return tRS( aBeg, aEnd, aDBeg, aDInner, aDEnd );
}
template
< class tStream
, class tItr
, class tDBeg
, class tDInner
, class tDEnd
>
inline tStream& operator<<
( tStream& s
, const range_streamer<tItr,tDBeg,tDInner,tDEnd>& aRS
)
{
aRS.OutputTo(s);
return s;
}
------------example usage -------------
std::ostream& operator<<( std::ostream& s, const CDictionary& aD )
{
s << range_stream( aD.mGroups.begin()
, aD.mGroups.end()
, "GroupList = \n{ "
, "\n, "
, "\n},"
);
typedef CDictionary::VarSpec tVar;
typedef tVar::tPtr tVarPtr;
typedef boost::indirect_iterator_generator //boost1.30 req's all
params
< CDictionary::tVars::const_iterator
, tVar
, tVar&
, tVar*
, std::iterator_traits<CDictionary::tVars::const_iterator
>::iterator_category>::type
tVarItr;
s << range_stream
( tVarItr( aD.mVars.begin() )
, tVarItr( aD.mVars.end() )
, "\nData =\n{ "
, "\n},\nData =\n{ "
, "\n}"
);
return s;
}
produces:
GroupList =
{ DEBUG
, plenum_flow
},
Data =
{ Name = x_0
, Type = double
},
Data =
{ Name = x_1
, Type = double
},
Data =
{ Name = dm_dt
, Type = float
}
-- Jeff Flinn Applied Dynamics, International "Victor A. Wagner, Jr." <vawjr_at_[hidden]> wrote in message news:6.0.0.22.2.20030903205520.040f3b00_at_mail.rudbek.com... > 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_at_[hidden] > http://lists.boost.org/mailman/listinfo.cgi/boost-users >
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net