【发布时间】:2020-06-03 23:55:12
【问题描述】:
考虑以下重载函数,它可以打印一维向量和多种类型的向量,如字符串、整数、双精度等。
template<typename T>
void p(const vector<vector<T>>& vec) {
int count = 0;
for (vector<T> innerVec: vec) {
cout << count++ << ": ";
for (T e :innerVec) {
cout << e << ' ';
}
cout << '\n';
}
cout << '\n';
}
template<typename T>
void p(const vector<T>& vec) {
for (T e: vec) {
cout << e << ' ';
}
cout << '\n';
}
无论如何我可以将这两个函数合并为 1 吗?我尝试使用 SFINAE 和标签调度,但我能想出的所有解决方案都需要一个宏或多个函数,我不想要这个。
我知道这个问题可能看起来很奇怪,因为我的解决方案有效,但我更喜欢在我的代码中只包含一个函数。这是因为我想实现一个函数,它可以检测我是否传入了一个映射、向量、向量的向量、unordered_set、multimap 等,并且只打印该 STL 数据结构,并且每个专业化都有一个重载函数有点烦人因为它变得很快。
【问题讨论】:
-
不是一个完整的解决方案,但您可以替换代码重复,在 2D 版本中,只需执行
cout << innerVec;另外,我真的建议通过const & -
无关:
vector<vector<T>> vec不是 2Dvector。它是一个vector,包含更多vectors。因此,可能会对性能产生很大影响。数据并非全部在一个连续的内存块中,因此它对缓存不是特别友好。 -
因为这两个函数的行为不同,所以在合并这两个函数时会遇到麻烦。您可以这样做:
template<typename T> std::ostream & operator<<(std::ostream & out, const std::vector<T>& vec) { for (T e: vec) { out << e << delimiter; } return out; },但分隔符会发生变化。您需要一些额外的巫术来检测何时处于叶子状态,因为没有更多容器,因此您可以交换分隔符。我承认吸巫术。 -
如果您从所需的输出中删除
0:等,那么您只需要template<typename Container, typename = std::void_t<typename Container::value_type>> std::ostream & operator<<(std::ostream & out, const Container& cont)和template<typename T1, typename T2> std::ostream & operator<<(std::ostream & out, const std::pair<T1, T2>& pair)即可涵盖所有内容。