有没有办法编写一个通用循环,它迭代stl map(关联容器(和列表(非关联容器(的值。
template<typename T>
void foo(T &t)
{
for (auto iter = t.begin(); iter != t.end(); ++iter)
{
printf("%dn", *iter); // will work for std::list<int> but not for std::map<int, int>
}
}
谢谢
要使其适用于 std::map - 使用来自 boost 的正确适配器:
foo(someMap | boost::adaptors::map_values);
你也可以使用 Eric Niebler 的 ranges-v3
foo(someMap | ranges::values);
如果您不能使用提升/范围 - 请使用某种特征:
template <typename ValueType>
struct ValueGetter
{
static Value& get(ValueType& value)
{
return value;
}
};
template <typename Key, typename Value>
struct ValueGetter<std::pair<const Key, Value>>
{
using ValueType = std::pair<const Key, Value>;
static Value& get(ValueType& value)
{
return value.second;
}
};
template <typename ValueType>
auto& getValue(ValueType& value)
{
return ValueGetter<Value>::get(value);
}
template<typename T>
void foo(T &t)
{
for (auto iter = t.begin(); iter != t.end(); ++iter)
{
printf("%dn", getValue(*iter));
}
}
实际上,已经有 std::for_each ( #include <algorithm>
( 用于此类目的。您可以使用适当的处理程序来喂养它,例如以 lambda 的形式:
std::vector<int> v;
std::map<int, double> m;
std::for_each(v.begin(), v.end(), [](auto i) { printf("%dn", i); });
std::for_each(m.begin(), m.end(), [](auto const& i) { printf("%d %fn", i.first, i.second); });
我确实喜欢阿空加瓜的显示方式,在大多数情况下,这将是我最喜欢的选择。
为了使它更清晰并填补我的评论的空白。作者在这里发布的循环还可以。在这种情况下,唯一的问题是关于printf()
。为了解决这个问题,我建议像重载流运算符((这样的东西,以便能够打印出std::map
ostream& operator<<(ostream& os, pair<string, int> it){
os << it.first << " => " << it.second;
}
正如您可能已经意识到的那样,在 std::map 的情况下,迭代器是这对。请注意,您无需为std::list
指定 ,泛型循环可能如下所示
template<typename T>
void foo(T &t){
for(auto it=t.begin(); it=t.end(); ++it){
cout << *it << endl;
}
}
这与问题中的内容很好,除了printf() => cout
.在这里,您还可以使用基于范围的循环
template<typename T>
void foo(T &t){
for(auto it : t)
cout << it << endl;
}
最后for_each()
函子或 lambda 表达式的一侧。