使用C++11中的std::for_each遍历std::set

7

迭代向量是可行的:

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&,为什么不能自动推导出它的类型?

4个回答

20

std::set<T>::value_typeT const,而不是 T;因此,您的 lambda 表达式的参数必须是值类型(即复制)或者是 int const&(严格来说,还可以是 int const volatile&),而不能是 int&。也就是说,以下代码可以正常工作:

std::set<int> collection{2, 3, 4, 5435345, 2};
std::for_each(
    collection.begin(),
    collection.end(),
    [](int const& i) { std::cout << i << std::endl; }
);

因为标准规定不能这样做;历史上,我认为这是由于 lambda 和概念之间过于复杂的交互(在概念从草案中删除之前)。然而,听说新(C++11)标准的第一个缺陷报告将正好解决这个问题,所以你可能会在未来一两年内看到对此的支持添加到您选择的编译器中。编辑:哦,看起来 C++14 现在有多态 lambda...

你从哪里听到的?在Herb Sutter的博客上,他提到在概念问题得到解决之前,他们不会添加多态lambda,因为他们仍然希望在未来实现类似于概念的功能。 - deft_code
哈哈,真是个政客。:) 那么,请把它从答案中删除,好吗? - wilhelmtell

3
关于奖励问题:一个“auto”函数参数并不特定于lambda表达式。你可以问为什么我们不允许所有函数都声明为“f(auto x, auto y)”。但这意味着你基本上想用函数模板来替换所有函数。考虑到现有的C++语言和类型系统,这被认为无法很好地工作。如果你想要一个函数模板,已经有现有的语法和机制,并且声明“auto”参数不是正确的方法。

1

解引用的 set<int> 迭代器是一个 const int&。因此,如果没有 const,您无法将其作为 int& 参数传递。请尝试使用普通的 (int i)(const int& i)

而且这真的不是你可以使用 auto 的地方之一。我认为 auto 只能在带有初始化程序的声明中或作为尾随返回类型的占位符中使用。


0
你应该能够迭代一个集合。但是请注意,由于集合中的元素也是其键,因此它不能被修改。将你的代码更改为使用const引用,并在不打算修改元素时始终使用cbegin/cend,无论是否为集合。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接