通用容器的输出流
Output stream for generic container
我创建了这个模板函数:
// Output stream for container of type C
template<class C>
ostream& operator<<(ostream& os, const C& c) {
os << "[";
for (auto& i : c) {
os << i;
if (&i != &c.back()) os << ", ";
}
os << "]" << endl;
return os;
}
但是我有这个错误:
error: use of overloaded operator '<<' is ambiguous (with operand
types 'std::ostream' (aka 'basic_ostream') and 'const char [2]')
错误在函数体的第一行。
这个声明
template<class C>
ostream& operator<<(ostream& os, const C& c)
匹配任何类型。特别是,当您在该 operator
内部调用时
os << "[";
os << i;
os << "]" << endl;
对于所有这些调用,除了已经存在的字符串和 endl
输出运算符之外,您的运算符也是一个匹配项。
不要为您不拥有的类型提供运算符。相反,你可以写一个
void print(const my_container&);
或者使用标签来解决歧义。例如,您可以使用
template <typename T>
struct pretty_printed_container {
const T& container;
};
template <typename T>
pretty_printed_container<T> pretty_print(const T& t) { return {t};}
相应地修改输出运算符
template<class T>
std::ostream& operator<<(std::ostream& os, const pretty_printed_container<T>& c) {
os << "[";
for (const auto& i : c.container) {
os << i;
if (&i != &c.container.back()) os << ", ";
}
os << "]" << std::endl;
return os;
}
然后像这样使用
int main() {
std::vector<int> x{1,2,3,4,5};
std::cout << pretty_print(x);
}
输出:
[1, 2, 3, 4, 5]
如果您可以访问 boost
库但不想使用 pretty_printed_container
,您可以执行以下操作:
#include <boost/spirit/home/support/container.hpp>
template <typename CharT, typename Traits, typename Container,
std::enable_if_t<boost::spirit::traits::is_container<Container>::value, int> = 0>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const Container& c) {
os << "[ ";
for (const auto& e : c)
os << e << " ";
return os << "]";
}
通过这种方式,您可以直接打印您的容器,甚至是嵌套的容器。
奖金:
添加此代码,您还可以将关联容器打印为 std::map
/// operator<< for printing pair, this is needed to print associative containers.
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
return os << "[" << p.first << ", " << p.second << "]";
}
例如:
int main() {
std::set<int> set{ 1, 2, 3, 4 };
std::vector<std::vector<int>> nestedVector{ {1, 2}, {3, 4} };
std::map<int, std::string> map{ {1, "one"}, {2, "two"}, };
std::cout << set << '\n';
std::cout << nestedVector << '\n';
std::cout << map << '\n';
}
将输出:
[ 1 2 3 4 ]
[ [ 1 2 ] [ 3 4 ] ]
[ [1, one] [2, two] ]
我创建了这个模板函数:
// Output stream for container of type C
template<class C>
ostream& operator<<(ostream& os, const C& c) {
os << "[";
for (auto& i : c) {
os << i;
if (&i != &c.back()) os << ", ";
}
os << "]" << endl;
return os;
}
但是我有这个错误:
error: use of overloaded operator '<<' is ambiguous (with operand types 'std::ostream' (aka 'basic_ostream') and 'const char [2]')
错误在函数体的第一行。
这个声明
template<class C>
ostream& operator<<(ostream& os, const C& c)
匹配任何类型。特别是,当您在该 operator
内部调用时os << "[";
os << i;
os << "]" << endl;
对于所有这些调用,除了已经存在的字符串和 endl
输出运算符之外,您的运算符也是一个匹配项。
不要为您不拥有的类型提供运算符。相反,你可以写一个
void print(const my_container&);
或者使用标签来解决歧义。例如,您可以使用
template <typename T>
struct pretty_printed_container {
const T& container;
};
template <typename T>
pretty_printed_container<T> pretty_print(const T& t) { return {t};}
相应地修改输出运算符
template<class T>
std::ostream& operator<<(std::ostream& os, const pretty_printed_container<T>& c) {
os << "[";
for (const auto& i : c.container) {
os << i;
if (&i != &c.container.back()) os << ", ";
}
os << "]" << std::endl;
return os;
}
然后像这样使用
int main() {
std::vector<int> x{1,2,3,4,5};
std::cout << pretty_print(x);
}
输出:
[1, 2, 3, 4, 5]
如果您可以访问 boost
库但不想使用 pretty_printed_container
,您可以执行以下操作:
#include <boost/spirit/home/support/container.hpp>
template <typename CharT, typename Traits, typename Container,
std::enable_if_t<boost::spirit::traits::is_container<Container>::value, int> = 0>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const Container& c) {
os << "[ ";
for (const auto& e : c)
os << e << " ";
return os << "]";
}
通过这种方式,您可以直接打印您的容器,甚至是嵌套的容器。
奖金:
添加此代码,您还可以将关联容器打印为 std::map
/// operator<< for printing pair, this is needed to print associative containers.
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
return os << "[" << p.first << ", " << p.second << "]";
}
例如:
int main() {
std::set<int> set{ 1, 2, 3, 4 };
std::vector<std::vector<int>> nestedVector{ {1, 2}, {3, 4} };
std::map<int, std::string> map{ {1, "one"}, {2, "two"}, };
std::cout << set << '\n';
std::cout << nestedVector << '\n';
std::cout << map << '\n';
}
将输出:
[ 1 2 3 4 ]
[ [ 1 2 ] [ 3 4 ] ]
[ [1, one] [2, two] ]