【问题标题】:Generic loop that iterates on both stl map and list (c++)在 stl 映射和列表上迭代的通用循环(c++)
【发布时间】:2018-03-12 08:35:36
【问题描述】:

有没有办法编写一个通用循环,它会遍历 stl 映射(关联容器)和列表(非关联容器)的值。

template<typename T>
void foo(T &t)
{
    for (auto iter = t.begin(); iter != t.end(); ++iter)
    {
        printf("%d\n", *iter); // will work for std::list<int> but not for std::map<int, int>
    }

}

谢谢

【问题讨论】:

  • 它们是两个不同的容器。我想你需要专门化你的函数模板。您可能需要重新考虑/放弃这种方法。已经有一个range based loop
  • 你有应该工作的通用循环,唯一的问题是这种方式的 printf() 函数确实不起作用。我建议使用 c++ 中的 cout,并重载流操作符以在屏幕上打印内容。
  • 它们有不同的语义,如果是地图,你想从*iter得到什么?
  • 你想达到什么目的?
  • @Rotem 通用循环,例如删除任何集合中的指针

标签: c++ templates stl


【解决方案1】:

为了使其适用于 std::map - 使用来自 boost 的正确 adapter

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("%d\n", getValue(*iter)); 
    }

}

【讨论】:

  • 您根据 Eric Niebler 的 github.com/ericniebler/range-v3 映射添加范围将添加到 C++ 标准。
  • @Jens 是的 - 我知道 - 我希望它会在 C++17 中。我会的。
【解决方案2】:

实际上,已经有 std::for_each (#include &lt;algorithm&gt;) 用于此类目的。你可以用适当的处理程序喂它,例如。 G。以 lambda 的形式:

std::vector<int> v;
std::map<int, double> m;

std::for_each(v.begin(), v.end(), [](auto i) { printf("%d\n", i); });
std::for_each(m.begin(), m.end(), [](auto const& i) { printf("%d %f\n", i.first, i.second); });

【讨论】:

    【解决方案3】:

    我确实喜欢Aconcagua 展示它的方式,在大多数情况下,这将是我最喜欢的选择。

    为了更清楚并填补我评论的空白。作者在这里发布的循环是可以的。在这种情况下,唯一有问题的是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() =&gt; cout 之外,问题中的内容都很好。在这里,您还可以使用基于范围的循环

    template<typename T>
    void foo(T &t){
        for(auto it : t)
            cout << it << endl;
    }
    

    最后是 for_each() 与仿函数或 lambda 表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 2011-04-02
      • 2012-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-11
      相关资源
      最近更新 更多