以下代码是我第一次尝试打印可迭代容器的C ++ 11。它使用功能模板默认参数功能。
#include <ostream>
#include <string>
#include <utility>
template <typename T>
void print(std::ostream &o, T const &t) { o<< t; }
void print(std::ostream &o, std::string const &s){ o<< '"'<< s<< '"'; }
template <typename K, typename V>
void print(std::ostream &o, std::pair<K, V> const &p)
{
o<< '{'; print(o, p.first);
o<< ": "; print(o, p.second);
o<< '}';
}
template <typename C, typename I= typename C::const_iterator>
std::ostream &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<< ']';
}
它适用于容器,容器容器等。但有一个例外:
std::cout<< std::string("wtf");
使用g ++ 4.7 / 8进行编译,说明ambiguous operator<<
。
是否有任何修复此代码以避免歧义?
答案 0 :(得分:2)
如果是字符串,您可以使用std::enable_if
来禁用重载:
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<< ']';
}
或更一般地做:
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<< ']';
}