gre*_*fab 47 c++ algorithm stl c++11
当使用STL的函数时,sort()或者min_element()我总是必须明确地指定开始和结束的范围:
void range_example()
{
std::vector<int> list = {7, 3, 9, 1, 5, 2};
auto found_element = std::min_element(list.begin(), list.end());
std::cout << *found_element << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
如果我打算只在我的容器的一部分上工作,这是有道理的,但更多时候我需要函数来处理整个容器.有没有一个原因,为什么没有一个重载函数允许这样做:
std::vector<int> list = {7, 3, 9, 1, 5, 2};
auto found_element = std::min_element(list);
Run Code Online (Sandbox Code Playgroud)
有没有办法完成我忽略的容器总范围的函数调用?
编辑:我知道我可以自己将其封装在一个函数中,但是因为必须对所有函数进行此操作,所以如果有更好的方法,我希望避免这种情况.
Rei*_*ica 43
大多数情况下,标准库旨在提供完成所需任务所需的最小接口,即它试图避免接口膨胀.当算法接受一对迭代器时,您可以对整个容器进行操作,但如果算法接受了容器,则无法对子范围进行操作.所以迭代器对更基础,所以这就是标准库提供的.通常不包括便利功能.
但是,你肯定不是第一个这样思考的人,并且整个Boost.Range库专门用于将范围(容器和任意范围)视为单个实体而不是一对迭代器.
还有一个正式的提议,将Eric Niebler的范围库合并到C++标准库的未来版本中.
这是因为STL算法与容器无关.迭代器为它们提供统一的工作方式,唯一的限制是这种算法从这些迭代器中得到的保证.
例如,如果要进行线性搜索min_element(),则只需要前向迭代器(即它们只需要支持operator++).因此,您可以编写一个简单的模板化实现,它基本上适用于每个容器,尽管容器是如何在引擎盖下实现的.
你可以重载功能,只需要在容器和应用begin(),并end()在他们身上,但是这将意味着你有一个多接口记住.
编辑
我想还有一些其他的论点可以做.由于STL完全是关于数学美,并强调算法与容器是分开的,所以总是传递迭代器会强化这个概念.
另一方面,就整个C++语言而言,Stroustrup的主要目标之一是教育开发人员.STL算法的全部功能来自于传递任意迭代器范围的能力,但大多数时候您希望在整个容器上运行.如果你为整个容器提供了重载,可以说很多人都不会费心去学习使用范围版本,因为正是这些版本会落入"另一个要记住的界面"类别.
容器或范围重载尚未完成的实际原因还与概念提议有关.
现在,算法采用了一堆模板参数,并对它们提出了要求.如果传递的类型与要求不匹配,则可能无法编译或无法正常工作.
过载几乎总是只涉及不同数量的参数.
如果我们在哪里添加容器/范围重载,那么我们要么必须给它们新名称(ick),要么修改现有算法以使其过载智能.(迭代器,迭代器,值)重载和(范围,值,函数)重载具有相同数量的参数,并且调用哪一个可能很容易使编译器混淆(并且可能发生意外结果).
虽然我们可以逐个指定所有现有算法的过载约束,然后添加范围的重载,此时代码和要求将是丑陋的.在将概念添加到语言之后,我们都希望有一组简明的概念来描述参数应该是什么,以及一个使实现变得简单和干净的语言特性.
可能会发现,由于兼容性原因或者你有什么原因,这些算法实际上可能不会是现有算法的重载,但即使这样也会更容易解决.
最初,迭代器足够了,它们将容器与算法分离.然后可以添加范围,但容器的清洁范围解释的语言机制有点缺乏(例如,decltype是有用的),并不是严格要求的.从那以后,一直需要范围支持,但要干净利落地做起来并不容易,而且(即将推出)语言扩展将使其更加清洁和简单.