我正在尝试使用C ++模板编写一段有趣的代码。
#include <iostream>
#include <vector>
template <class Container>
std::ostream& operator<<(std::ostream& o, const Container& container)
{
typename Container::const_iterator beg = container.begin();
o << "["; // 1
while(beg != container.end())
{
o << " " << *beg++; // 2
}
o << " ]"; // 3
return o;
}
int main()
{
std::vector<int> list;
list.push_back(0);
list.push_back(0);
std::cout << list;
return 0;
}
以上代码无法编译:)
在1,2,3处产生相同的错误:错误C2593:'operator&lt;&lt;'含糊不清
我想要做的就是重载&lt;&lt;操作员使用任何容器。那有意义吗 ?怎么可能呢?如果可能的话,如果不是为什么?
编辑::感谢您的更正:)'某事'是一个很好的解决方案。
我很好奇,如果我们可以使用C ++ 0x概念,这种歧义 - 如Neil解释的那样 - 会消失吗?
答案 0 :(得分:7)
您可以限制您的运营商&lt;&lt;通过指定Container模板参数本身是模板化的,仅应用于模板化容器。由于C ++ std容器也有一个allocator模板参数,你还必须将它包含在Container的模板参数中。
template
< typename T
, template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container
>
std::ostream& operator<< (std::ostream& o, const Container<T>& container)
{
typename Container<T>::const_iterator beg = container.begin();
o << "["; // 1
while(beg != container.end())
{
o << " " << *beg++; // 2
}
o << " ]"; // 3
return o;
}
int main()
{
std::vector<int> list;
list.push_back(0);
list.push_back(0);
std::cout << list;
return 0;
}
答案 1 :(得分:4)
新定义的operator<<
不仅匹配容器,还匹配任何其他类型,如整数和字符串。这就是编译器在需要找到匹配的operator<<
来输出"["
时抱怨含糊不清的原因。
解决此问题的一种方法是重命名输出函数:
template <class Container>
std::ostream& container_out(std::ostream& o, const Container &container) {
// ...
}
然后,您可以为要打印的所有容器添加简单包装器以启用operator<<
:
template<typename T>
std::ostream& operator<<(std::ostream& o, const std::vector<T> &container) {
return container_out(o, container);
}
template<typename T>
std::ostream& operator<<(std::ostream& o, const std::map<T> &container) {
return container_out(o, container);
}
答案 2 :(得分:3)
错误是什么?我看到一个,你需要一个类型名称:
typename Container::iterator beg = container.begin();
这里发生的事情是编译器在第一次阅读时对Container一无所知。所以我们必须给它一点帮助并告诉它迭代器将是一个类型(从语法上讲它可以是类范围内的任何有效名称,所以函数,变量,......)。编写模板方法时,任何依赖于模板类型的类型都必须指定它是具有关键字typename
的类型。
答案 3 :(得分:2)
您的操作员介绍了它自己的模糊性 - 它本身可以用于打印它试图打印的东西。我的建议:
答案 4 :(得分:1)
好的,现在你的模板会造成混乱。编译器无法在您的运算符和您期望的运算符之间做出决定。
答案 5 :(得分:1)
可能不像你发布的那样通用(你需要传递包含的类型),并且最后还留下了一个额外的分隔符,但你可以使用STL:
std::vector<int> v;
v.push_back( 10 );
v.push_back( 20 );
std::cout << "[";
std::copy( v.begin(), v.end(), std::ostream_iterator<int>( std::cout, " " ) );
std::cout << "]";
将输出:
[10 20]
请注意,额外的分隔符位于序列的末尾,并且[和第一个元素之间没有初始空格。
答案 6 :(得分:0)
http://blog.csdn.net/cqdjyy01234/article/details/19234329可能是一个很好的解决方案。它适用于STL容器和C风格的数组。