C++ std::for_each没有写入std::list的原因是什么?

C++ std::for_each没有写入std::list的原因是什么?,c++,c++11,C++,C++11,我意识到这相当于语法上的糖分,但是,随着lambda的出现,我希望能够打字 std::for_each(list, [](Emitter& e) { e->emit() }); 而不是 std::for_each(list.begin(), list.end(), ....); 我知道后者更通用,但它们可以同时提供AFAICT和AFAICT,前者只是另一个模板函数,猜怎么着?你可以通过为每个函数定义自己的函数: template <class C, class F>

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

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

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

我知道后者更通用,但它们可以同时提供AFAICT和AFAICT,前者只是另一个模板函数,猜怎么着?你可以通过为每个函数定义自己的函数:

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

你可以在这里看到一个活生生的例子:

猜怎么着?你可以通过为每个函数定义自己的函数:

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

您可以在这里看到一个实例:

标准算法处理范围,而不是容器。这是一个深思熟虑的设计决定。标准库不应膨胀。如果您想自己添加此功能,您只需简单地添加即可。

标准算法适用于范围,而不是容器。这是一个深思熟虑的设计决定。标准库不应膨胀。如果你想自己添加这个功能,你可以随意添加。

因为我不在委员会,下面是推测。但对我来说似乎是合法的

std::for_each没有写入std::list的原因是什么

代码膨胀

为每个开始、结束和每个容器提供这两者实际上是多余的。毕竟,正如你所说,你可以简单地为每个c.begin、c.end编写代码,并得到你想要的行为

由于您所建议的版本只是语法上的糖衣,并且比作为库的一部分(使用开始和结束迭代器)的版本更具限制性,因此添加它是没有意义的

我想你可以把这看作是“不要为你不想要的东西付费”哲学的一个扩展,它指导了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);
  }
}

既然我不在委员会,接下来就是猜测。但对我来说似乎是合法的

std::for_each没有写入std::list的原因是什么

代码膨胀

为每个开始、结束和每个容器提供这两者实际上是多余的。毕竟,正如你所说,你可以简单地为每个c.begin、c.end编写代码,并得到你想要的行为

由于您所建议的版本只是语法上的糖衣,并且比作为库的一部分(使用开始和结束迭代器)的版本更具限制性,因此添加它是没有意义的

我想你可以把这看作是“不要为你不想要的东西付费”哲学的一个扩展,它指导了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);
  }
}

随着lambdas的出现,以下是基于范围的循环:

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

随着lambdas的出现,以下是基于范围的循环:

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

在C++11之前提供这两个容器并不容易,这两个都意味着它支持所有容器,而不仅仅是std::list。有一个范围研究小组正在做这件事。定义范围x.begin,x.end将是做你想做的事情的肮脏方式…@tmyklebu。。。真讨厌:-@chris。。。谢谢很高兴知道有人在考虑这件事。正如我在下面提到的,我很欣赏std库中的公理化方法,但如果它导致每个人都编写不必要的冗长代码或Hiura提出的模板,我认为应该考虑将其包含在内。在C++11之前提供这两种方法并不容易,这两种方法都意味着它支持所有容器,而不仅仅是std::list。有一个范围研究小组正在做这件事。定义范围x.begin,x.end将是做你想做的事情的肮脏方式…@tmyklebu。。。真讨厌:-@chris。。。谢谢很高兴知道有人在考虑这件事。正如我在下面提到的,我可以欣赏std库中的公理化方法,但如果它导致每个人都编写不必要的冗长代码或Hiura提出的模板,我认为应该考虑将其包含在内。对于C++11,更好的是,std::beginc和std::endc。然后它也适用于普通数组。如果lambda表达式被反转,那么它将读取list@Brian正当我倾向于忘记那些自由函数。。。代码更新@布莱恩:不是std::beginc,而是使用std::begin;其次是beginc公司。end也一样。@Hiura:这样做会将beginc执行的查找类型从限定名称查找更改为非限定名称查找。非限定名称查找包括依赖于参数的查找,因此名为begin的函数与c类型在同一名称空间中,或者,遗憾的是,与c类型的模板参数类型在同一名称空间中-我认为这是一个错误,同时还会发现std::begin。这允许更好的扩展性。对于C++11,更好的是std::beginc和std::endc。然后它也适用于普通数组。如果lambda表达式被反转,那么它将读取list@Brian
正当我倾向于忘记那些自由函数。。。代码更新@布莱恩:不是std::beginc,而是使用std::begin;其次是beginc公司。end也一样。@Hiura:这样做会将beginc执行的查找类型从限定名称查找更改为非限定名称查找。非限定名称查找包括依赖于参数的查找,因此名为begin的函数与c类型在同一名称空间中,或者,遗憾的是,与c类型的模板参数类型在同一名称空间中-我认为这是一个错误,同时还会发现std::begin。这允许更好的扩展性。为什么会返回迭代器?@K-ballo:Oops。修正了。在我看来,更紧凑的代码总是一件好事,我不确定它是否算作代码膨胀/随玩随付,因为Hiura编写的模板定义实际上是我想象的,隐藏在std::imports后面。话虽如此。我可以欣赏标准库中更公理化的方法。为什么这会返回迭代器?@K-ballo:Oops。修正了。在我看来,更紧凑的代码总是一件好事,我不确定它是否算作代码膨胀/随玩随付,因为Hiura编写的模板定义实际上是我想象的,隐藏在std::imports后面。话虽如此。我可以欣赏标准库中更公理化的方法。+1-for_基本上已经过时了,除了一些特殊情况。这个角落案例涉及的代码看起来像其他算法一样。除了一些角落案例外,每个+1-for_基本上是过时的。那个角落里的案例涉及的代码看起来像其他算法。