You can use std::enable_if
to disable your overload in the case of a string:
template <typename C, typename I= typename C::const_iterator>
typename std::enable_if<!std::is_same<C,std::string>::value,std::ostream>::type &
operator<< (std::ostream &o, C const &c)
{
o<< '[';
if(c.empty()) return o<< ']';
I b= c.begin(), e= c.end(); -- e;
for(; b!= e; ++ b)
{
print(o, *b);
o<< ", ";
}
print(o, *b);
return o<< ']';
}
or to do it more generically:
template <typename T>
struct is_string : std::false_type {};
template <typename Char,typename Allocator>
struct is_string<std::basic_string<Char,Allocator> > : std::true_type {};
template <typename C, typename I= typename C::const_iterator>
typename std::enable_if<!is_string<C>::value,std::ostream>::type &
operator<< (std::ostream &o, C const &c)
{
o<< '[';
if(c.empty()) return o<< ']';
I b= c.begin(), e= c.end(); -- e;
for(; b!= e; ++ b)
{
print(o, *b);
o<< ", ";
}
print(o, *b);
return o<< ']';
}