C++打印模板容器错误(错误:"运算符<<"的不明确重载)理解?
C++ print template container error (error: ambiguous overload for 'operator<<') understanding?
我想写一个模板函数,它可以打印像std::vector
,std::list这样的容器。
下面是我的函数,只过载<<
。
template<typename Container>
std::ostream& operator<<(std::ostream& out, const Container& c){
for(auto item:c){
out<<item;
}
return out;
}
测试代码如下:
int main(){
std::vector<int> iVec{5, 9, 1, 4, 6};
std::cout<<iVec<<std::endl;
return 0;
}
输出:
59146
我想在每个值中添加一个空格字符串(输出类似于5 9 1 4 6
(,所以我将函数更改为:
template<typename Container>
std::ostream& operator<<(std::ostream& out, const Container& c){
for(auto item:c){
out<<item<<" ";
}
return out;
}
然后它得到错误:
merror: ambiguous overload for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'const char [2]')
out<<item<<" ";
我知道<<
可以输出类似的常见类型。
int a = 0;
double f = 0.3;
std::string s = "123";
std::cout<<a<<f<<s<<std::endl;
那么为什么会出现上述错误呢?有什么办法解决吗?
我看到了这个问题"operator<lt;'在'std::cout<lt;但我还是听不清楚。
所有代码:
#include <iostream>
#include <vector>
template<typename Container>
std::ostream& operator<<(std::ostream& out, const Container& c){
for(auto item:c){
out<<item;
// out<<item<<" "; // error
}
return out;
}
int main(){
std::vector<int> iVec{5, 9, 1, 4, 6};
std::cout<<iVec<<std::endl;
return 0;
}
声明template<typename Container>
可能很危险,因为此模板包括"all"变量类型int
、char
等。由于此编译器不知道要使用哪个operator<<
。
为了只获取容器类型变量,请使用模板中的模板。这是的工作代码
template<typename T, template <typename, typename> class Container>
std::ostream& operator<<(std::ostream& out, const Container<T, std::allocator<T>>& c) {
for (auto item : c) {
out << item << " ";
}
return out;
}
int main()
{
cout << "Hello world" << endl;
int arr[] = { 0,3,6,7 };
vector<int> v(arr, arr+4);
cout << v << endl;
return 0;
}
@miradham很好地解释了这个问题。
但这是一个更通用的解决方案,使用SFINAE使重载只考虑可以使用基于范围的for循环的类型,无论它们的模板参数是什么。
来自std::basic_string
的类型被忽略,以防止与显示字符串的标准operator <<
产生歧义
c样式数组将不会使用此重载显示,即使它们可以显示,因为它们衰减为指针并使用标准operator <<
显示
#include <iostream>
#include <vector>
#include <type_traits>
#include <array>
#include <string>
template<template<typename...> typename From, typename T>
struct is_from : std::false_type {};
template<template<typename...> typename From, typename ... Ts>
struct is_from<From, From<Ts...> > : std::true_type {};
template <typename...>
using void_t = void;
template <typename T, typename = void>
struct is_input_iterator : std::false_type { };
template <typename T>
struct is_input_iterator<T,
void_t<decltype(++std::declval<T&>()),
decltype(*std::declval<T&>()),
decltype(std::declval<T&>() == std::declval<T&>())>>
: std::true_type { };
template<typename Container,
typename std::enable_if<is_input_iterator<decltype(std::begin(std::declval<Container>()))>::value &&
is_input_iterator<decltype(std::end(std::declval<Container>()))>::value &&
!is_from<std::basic_string, Container>::value, int>::type = 0>
std::ostream& operator<<(std::ostream& out, const Container& c){
for(const auto& item:c){
out << item << " ";
}
return out;
}
int main(){
std::array<int, 6> arr{0, 1, 2, 3, 4, 5};
std::vector<int> vec{5, 9, 1, 4, 6};
std::cout << vec << std::endl;
std::cout << arr << std::endl;
std::cout << std::string("test") << std::endl;
return 0;
}
问题是模板化类型Container可以匹配任何类型,而不仅仅是容器。其中包括您要打印的" "
。
如果您查看来自其他编译器的错误消息:https://godbolt.org/g/3YKtca
<source>:5:15: note: candidate function [with Container = char [2]]
std::ostream& operator<<(std::ostream& out, const Container& c){
也许您希望vector<T>
的部分专门化只取向量。确定一个类型是否是容器是一个更复杂的问题。
#include <iostream>
#include <vector>
template<typename E, typename A>
std::ostream& operator<<(std::ostream& out, const std::vector<E, A>& c){
for(auto item:c){
out<<item;
out<<item<<" "; // error
}
return out;
}
int main(){
std::vector<int> iVec{5, 9, 1, 4, 6};
std::cout<<iVec<<std::endl;
return 0;
}
https://godbolt.org/g/NJNwmN
问题是,您定义的operator<<
与std::vector
和const char (&array)[N]
(您试图流式传输到out
的" "
类型(都匹配。
演示问题的简化代码示例:
#include <iostream>
template<typename Container>
std::ostream& operator<<(std::ostream& out, const Container& c)
{
return out;
}
int main()
{
std::cout<<" "<<std::endl;
return 0;
}
以下示例仅将operator<<
限制为std::vector
s:
template<typename ... Args>
std::ostream& operator<<(std::ostream& out, const std::vector<Args...>& c)
{
for(auto item:c){
out<<item<<" ";
}
return out;
}
活生生的例子。
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- &lt;&lt;操作员在C 中超载错误
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- '&lt;'''&lt;'''&quot的模板类错误''令牌”
- 在尝试超载&lt;&lt;时链接错误2005和1169操作员
- 错误:没有匹配'运算符<<"在'std::cout
- 过载<<比如cout错误
- 重载& lt; & lt;为什么我得到以下错误
- 重载ostream&时转换错误无效;operator< & lt;
- 重载<<运算符错误C2804:二进制'运算符<<'参数太多
- 编译器错误,包括'<'代币
- 重载& lt; & lt;错误