Templates 采用STL思维模式的技巧

Templates 采用STL思维模式的技巧,templates,collections,stl,iterator,Templates,Collections,Stl,Iterator,在过去的6年里,我几乎完全是一名C程序员。我现在正在研究一个C++语言是一个选择的语言项目,STL是我们的集合库。 在使用C的LINQ之后,我很难进入STL的思维模式 例如:编写IEnumerator.Select的等效项 C 超级容易 现在尝试编写类似于C++和STL的东西。撇开yield关键字和匿名函数的方便语法问题不谈 如果不先回答一些困难的问题,这甚至是不可能的。因为STL枚举器使用枚举器间比较而不是MoveNext,所以必须确定枚举器的终值。然后,你必须处理所有迭代器的胡说八道。STL

在过去的6年里,我几乎完全是一名C程序员。我现在正在研究一个C++语言是一个选择的语言项目,STL是我们的集合库。 在使用C的LINQ之后,我很难进入STL的思维模式

例如:编写IEnumerator.Select的等效项

C

超级容易

现在尝试编写类似于C++和STL的东西。撇开yield关键字和匿名函数的方便语法问题不谈

如果不先回答一些困难的问题,这甚至是不可能的。因为STL枚举器使用枚举器间比较而不是MoveNext,所以必须确定枚举器的终值。然后,你必须处理所有迭代器的胡说八道。STL使用编译时模板分派而不是运行时动态分派,因此迭代器不仅必须根据输入枚举器的值\类型进行模板化,还必须根据特定类型的输入枚举器进行模板化

当我尝试在STL中编写映射联接迭代器时,请不要让我开始

通过查看其他人编写的代码,我得出的结论是,STL未经Boost整理,很少用于集合和排序之外的任何其他用途

我最近的观察结果是:

有没有办法在STL中简洁地编写一个变异迭代器? 如何将一个集合简洁地排序并复制到另一个集合中? 更一般地说,我注意到一些与我习惯的思维方式相冲突的事情:

STL代码似乎并不简洁。在编写STL代码时,我编写简洁代码的目的是一种负担吗?我的意思是,不简洁通常涉及很长的类型标识符 Boost似乎是在STL中编写算法的基本要求。不允许使用Boost的人会做什么?
你的一些问题对我来说没什么意义。例如,您谈到必须处理枚举数特征。我不太清楚你在说什么。也许你是说迭代器?我不记得使用过任何一种叫做枚举器的特性,我也不能在C++标准中找到任何这样的东西。 迭代器特性至少是存在的,但我很少弄乱它们。我很清楚他们的存在,但仅此而已。我已经写了相当多的迭代器和算法,但从来没有在其中任何一个方面做过任何具体的迭代器特性

让我们来讨论创建一个新集合的具体问题,该集合是另一个集合的排序版本。这在许多不同的方面都相当容易。std::部分排序拷贝当然可以做到:

#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>

int main() { 

    std::vector<int> input;

    // generate some data to sort
    std::generate_n(std::back_inserter(input), 20, rand);

    // a destination for the sorted data:
    std::vector<int> result(input.size());

    // do the sort/copy:
    std::partial_sort_copy(input.begin(), input.end(),
        result.begin(), result.end());

    // show the sorted data:
    std::copy(result.begin(), result.end(), 
        std::ostream_iterator<int>(std::cout, "\n"));

    return 0;
}
但是,出于许多目的,制作副本然后排序更容易:

std::vector<int> result(input.begin(), input.end());
std::sort(result.begin(), result.end());
如果您真的希望它简洁,可以将其复制到一个天生排序的数据结构中:

std::multiset<int> result(input.begin(), input.end());

然而,最后一种方法通常会牺牲一点效率以缩短代码。在许多情况下,大多数?这不是问题,但如果你觉得速度太慢,那么很容易找到更快的替代方案。

不,流程已经中断,但其余的都很好。Boost和QT都将STL扩展到更大的框架中,Boost作为一个通用扩展,QT用于GUI相关的东西。如果我理解IEnumerator.Select正确,我们称之为boost::transform\u迭代器。如果我理解boost::zip_迭代器,那就是你的map join迭代器。我应该注意,我的项目要求禁止boost。你应该看看标题提供了什么。这与其说是一个真正的问题,不如说是一个咆哮。也许这会有助于实际描述至少一件你真正想要完成的事情,而不是简单地叫嚷C是多么美妙和/或你是如何看待STL的。@肯尼特贝伦基:好的,但是你还没有给出任何关于问题的细节。在大多数情况下,IEnumerable.select与std::transform的顺序相同,只是transform会立即生成结果,而select会创建一个按需生成结果的对象。是这种差异导致了你的困难吗?如果没有,是什么?这里有一个只有一个副本的排序:。21行。我键入的最长标识符是std::vector。还有一个转换迭代器:。26行。更复杂,还是没那么糟糕。正如Jerry所说,正常的情况是,只需std::一次转换它们。@Mooing Duck在转换迭代器的实现中有一个重要的、不明显的、普遍适用的启示。在端点迭代器上调用make_transform对LINQ程序员来说并不明显,而且似乎是一种很好的方法。@KennetBelenky:哦,很高兴听到这个消息。这是STL中的一个常见技巧,因为正如您所说,类型名可能很长。创建元组、共享和其他。
std::multiset<int> result(input.begin(), input.end());