help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to have generic character literals?


From: Earl Purple
Subject: Re: How to have generic character literals?
Date: 10 Aug 2006 08:39:43 -0700
User-agent: G2/0.2

Siegfried wrote:
> Here is my attempt to write a generic output function but it does not
> compile. Can someone correct it for me? The problem is with the call to
> widen.
>
> Also, is it possible to make this more generic so it is not specific to
> class vector?
>
> Thanks,
> Siegfried
>
> template<typename CH, typename TY>
> std::basic_ostream<CH>& operator<<(std::basic_ostream<CH>& cout, const
> std::vector<TY>& vec){
>     std::copy(vec.begin(),vec.end(),
> std::ostream_iterator<TY,CH>(cout,cout.widen(',')));
>     //for(typename std::vector<TY>::const_iterator pE = vec.begin(); pE
> != vec.end(); pE++) cout<<(pE == vec.begin()?"[":",")<<*pE;  cout
> <<"]";
>     return cout;
> }

1. You should not specialise operator<< on a type that is not your own.
vector is not your own type, so you should put in an adapter.

2. widen returns a character type, but the second parameter to
ostream_iterator's constructor is const CH*. You can fix that by doing
this

template < typename CH, typename SQ > // where SQ is a sequence-type
std::basic_ostream<CH> & operator<<
  (
     std::basic_ostream<CH> & os // I don't like your use of cout, it's
confusing
     const SQ & seq
  )
{
   CH delim[2];
   typedef typename seq::value_type TY;
   delim[0] = os.widen( ',' );
   delim[1] = os.widen( '\0' ); // or use the traits eos
   std::copy
    (
      seq.begin(), seq.end(), // must exist for type seq
      std::ostream_iterator< TY >( os, delim )
   );

   return os;
}

3. Your issue about vector - perhaps the code above will work for any
sequence that has begin() and end() defined and value_type that can be
output. My suggestion though is that you make your own adapter that has
all these features.

Of course for std::map the value_type is not your own type (it's
std::pair) so either you use std::transform whenever you know it's a
map and want to output it in your own way (you can specialise the above
template for that case) or you have a type (value_type in your
sequence) that is not the pair type in the map but has an implicit
constructor from it (which would probably work).

I would also suggest that instead of enforcing a comma delimiter, as
you are writing your own adapter anyway you may as well allow the user
to specify their delimiter and store it in the adapter. You can provide
a default one.

You will probably want a function to create the adapter that resolves
template parameters and might even have the same name for different
sequence types. Put the adapter in your own namespace and define
operator<< above in the same namespace.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]