我正在尝试为stl容器重载operator<<()
(即插入器运算符)(例如vector
,list
,array
)(即任何支持基于范围的容器for循环,其value_type
也有operator<<()
的重载。我写了以下模板函数
template <template <class...> class TT, class ...T>
ostream& operator<<(ostream& out, const TT<T...>& c)
{
out << "[ ";
for(auto x : c)
{
out << x << " ";
}
out << "]";
}
适用于vector
和list
。但是当我尝试为array
int main()
{
vector<int> v{1, 2, 3};
list<double> ld = {1.2, 2.5, 3.3};
array<int, 3> aa = {1, 2, 3};
cout << v << endl; // okay
cout << ld << endl; // okay
cout << aa << endl; // error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
// cout << aa << endl;
// ^
}
为什么它不适用于array
?
有没有解决这个问题的工作?
我在互联网上搜索了SO以查找是否有办法为stl容器重载operator<<()
。
我已经在overloading << operator for c++ stl containers中阅读了答案,但它没有回答我的问题。
Pretty-print C++ STL containers中的答案似乎与我相符。
g ++版本:
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
编译命令:
g++ -std=c++11
答案 0 :(得分:3)
看看template <class...> class TT
。此参数适用于模板,任何接受任意数量类型参数的模板。
现在看看std::array<class T, std::size_t N>
。此模板不接受类型作为第二个参数。它接受一个整数常数。
因此它不能是您定义的模板函数的参数,并且模板参数推导因此而失败。
至于使其工作,最简单的方法是提供仅接受std::array
的(模板化)重载。模板参数将是(推导的)数组参数。
template<typename T, std::size_t N>
ostream& operator<<(ostream& out, std::array<T, N> const& a)
{
out << "[ ";
for(auto x : a)
{
out << x << " ";
}
out << "]";
return out;
}
答案 1 :(得分:3)
您的重载不适用于std::array
,因为它与std::array
使用的模板不匹配。与所有其他标准容器不同,std::array
在其模板参数列表中具有非类型模板参数。它被定义为
template<typename T, std::size_t N>
struct array;
这不适用于template <template <class...> class TT, class ...T>
,因为它只使用类型而不允许使用非类型std::size_t N
部分。
如果你添加这个重载它应该工作
template <class T, std::size_t N>
ostream& operator<<(ostream& out, std::array<T, N>& c)
{
out << "[ ";
for(auto x : c)
{
out << x << " ";
}
out << "]";
return out;
}
另请注意,您没有在重载中返回out
。这是未定义的行为,因为您告诉编译器您正在返回一些内容,但是您没有这样做。