std::for_each 优于 std::set,C++11
迭代向量有效:
std::vector<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});
但不能迭代集合(编译错误):
std::set<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});
为什么我不能使用 std::for_each
迭代 std::set
?
奖金问题: 另外,我想将 lambda 参数中的 int&
更改为 auto&
,为什么不能自动推导呢?
Iterating over a vector works:
std::vector<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});
but not over a set (compile error):
std::set<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});
Why can't I iterate over a std::set
with std::for_each
?
Bonus question:
Also, I would like to change the int&
in the lambda's argument to auto&
, why can't this be automatically deduced?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
std::set::value_type
是T const
,而不是T
;因此,lambda 的参数必须是值类型(即复制)或int const&
(从技术上讲,或int const volatile&
),而不是int&
.即,这有效:因为标准说不能;从历史上看,我认为这是由于 lambda 和概念之间的交互过于复杂(在概念从草案中删除之前)。
但是,我听说有传言称新 (C++11) 标准的第一个缺陷报告将准确解决这个问题,因此您可能会在明年或之内看到对此添加到您选择的编译器中的支持二.编辑:哦,看,C++14 现在有了多态 lambda...std::set<T>::value_type
isT const
, notT
; consequently, the argument to your lambda must be a value type (i.e., copy) orint const&
(and technically, orint const volatile&
), notint&
. I.e., this works:Because the standard says it can't; historically, I believe this was due to overly-complicated interactions between lambdas and concepts (before concepts were removed from the draft).
However, I hear rumors that the first defect reports to the new (C++11) standard will address exactly this, so it's possible that you'll see support for this added to your compiler of choice within the next year or two.EDIT: Oh, look, C++14 now has polymorphic lambdas...关于额外的问题:“auto”函数参数并非特定于 lambda。您可能还会问为什么我们不允许将所有函数声明为
f(auto x, auto y)
。但这仅仅意味着您本质上希望用函数模板替换所有函数。这被认为不适用于现有的 C++ 语言,尤其是类型系统。如果您想要一个函数模板,那么已经有现有的语法和机制,并且声明“自动”参数不是正确的方法。Concerning the bonus question: An "auto" function argument isn't specific to lambdas. You might as well ask why we don't allow all functions to be declared as
f(auto x, auto y)
. But that just means that you essentially want to replace all functions by function templates. That was considered not to work well with the existing C++ language and the type system in particular. If you want a function template, there's already an existing syntax and mechanism, and declaring "auto" arguments is not the way to go.解引用的
set
迭代器是一个const int&
。因此,如果没有const
,则无法将其作为int&
参数传递。尝试简单的(int i)
或(const int& i)
。这确实不是您可以使用
auto
的地方之一。我认为 auto 仅适用于带有初始值设定项的声明或作为尾随返回类型的占位符。A dereferenced
set<int>
iterator is aconst int&
. So you can't pass it as anint&
parameter without theconst
. Try either plain(int i)
or(const int& i)
.And that's really not one of the places you're allowed to use
auto
. I thinkauto
only works in a declaration with initializer or as a placeholder for a trailing return type.您应该能够迭代一组。但是,请注意,由于集合中的元素也是其键,因此无法修改。当您不打算修改元素时,更改代码以采用
const
引用,并使用cbegin/cend
代替,无论是否是集合。You should be able to iterate over a set. However, note that since the element in a set its also its key, it cannot be modified. Change your code to take a
const
reference, and usecbegin/cend
instead, regardless of whether is a set or not when you are not going to modify the elements.