[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.