【问题标题】:Is there a reason std::for_each was not written to take a std::list?没有编写 std::for_each 来获取 std::list 是否有原因?
【发布时间】:2014-04-10 03:15:24
【问题描述】:

我意识到它相当于语法糖,但是随着 lambda 的出现,我希望能够打字

std::for_each(list, [](Emitter& e) { e->emit() });

而不是

std::for_each(list.begin(), list.end(), ....);

我知道后者更普遍可用,但他们可以同时提供两者(AFAICT 前者只是另一个模板函数)

【问题讨论】:

  • 在 C++11 之前提供这两者并不容易,这意味着它支持所有容器,而不仅仅是std::list。除其他事项外,还有一个 Ranges 研究小组正在研究此问题。
  • #define RANGE(x) (x).begin(), (x).end() 将是做你想做的事情的讨厌方式......
  • @tmyklebu... 确实很讨厌 :-)
  • @chris...谢谢...很高兴知道有人在考虑它。正如我在下面提到的,我可以欣赏标准库中的公理化方法,但如果它导致每个人都编写不必要的冗长代码(或 Hiura 提出的模板),我认为应该考虑将其包含在内。

标签: c++ c++11


【解决方案1】:

你猜怎么着?你可以! ;-) 通过定义你自己的for_each 函数:

template <class C, class F>
F for_each(C const& c, F f) {
    return std::for_each(std::begin(c), std::end(c), f);
}

你可以在这里看到一个活生生的例子:http://ideone.com/gwGNGL

【讨论】:

  • 对于 C++11,更好的是 std::begin(c)std::end(c)。然后它也适用于普通数组。
  • 如果那个 lambda 表达式被倒转成“for each int in list”就更好了
  • @Brian 对!我倾向于忘记那些免费功能...代码更新了!
  • @Brian:不是std::begin(c),而是using std::begin;,然后是begin(c)end 也一样。
  • @Hiura:这样做会将begin(c) 的查找类型从限定名称查找更改为非限定名称查找。非限定名称查找包括依赖于参数的查找,因此名为 begin 的函数与 c 的类型在同一命名空间中(或者,遗憾的是,c 类型的模板参数的类型 - this ,我认为是一个错误)将被找到以及std::begin。这允许更好的可扩展性。
【解决方案2】:

随着 lambda 的出现,这里也出现了基于范围的 for 循环:

for (auto &e: list)
    e.emit();

【讨论】:

  • +1 -- for_each,除了一些极端情况,基本上已经过时了。 (涉及代码的极端案例看起来像其他算法)。
【解决方案3】:

标准算法适用于范围,而不适用于容器。这是一个深思熟虑的设计决定。标准库不应该臃肿。如果你想自己添加这个功能,你可以轻松做到。

【讨论】:

    【解决方案4】:

    由于我不是委员会成员,以下是猜测。但对我来说似乎是合法的。

    std::for_each 没有写入 std::list 是否有原因?

    代码膨胀。

    同时提供for_each (begin, end)for_each (container) 实际上是多余的。毕竟,正如你所说,你可以简单地写for_each (c.begin(), c.end()) 并得到你想要的行为。

    由于您建议的版本只是语法糖,并且比作为库一部分的版本(采用 beginend 迭代器)更具限制性,因此添加它没有意义。

    我想您可以将其视为“不为您不想要的东西买单”理念的延伸,该理念指导了 C++ 的大部分整体设计。正如前面提到的,您可以非常简单地提供您自己的相当通用的功能。下面是一些 psudocde 说明:

    namespace blah
    {
      template <typename Cont, typename UnaryFunction> inline UnaryFunction for_each (Cont& cont, UnaryFunction f)
      {
        return std::for_each (cont.begin(), cont.end(), f);
      }
    }
    

    【讨论】:

    • 为什么会返回一个迭代器?
    • @K-ballo:哎呀。固定。
    • 看起来更紧凑的代码始终是 IMO 的一件好事,我不确定它是否算作代码膨胀/自模板定义以来即付即用(实际上 Hiura 写的正是我所设想的) ) 是潜在的并隐藏在 std:: 导入后面。话说回来。我可以欣赏标准库中更公理化的方法。
    猜你喜欢
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    相关资源
    最近更新 更多