采用STL框架的提示

时间:2012-04-04 18:35:40

标签: templates collections stl iterator

在过去的6年里,我几乎都是C#程序员。我现在正在开发一个项目,其中C ++是首选语言,STL是我们的集合库。

在使用C#的LINQ之后,我很难进入STL框架。

作为一个例子:写一个等效的IEnumerator.Select。

C#

public static IEnumerator<Output> Select(this IEnumerator<Input> input, Func<Input, Output> func) {
  while (input.MoveNext) {
    yield return func(input.Current);
  }
}

非常容易。

现在尝试用C ++和STL编写类似的东西。 (抛开yield关键字和匿名函数的方便语法问题)。

如果没有先回答一些棘手的问题,甚至无法做到。由于STL枚举器使用的是枚举器间比较而不是MoveNext,因此您必须确定枚举器的终端值。然后你必须弄乱所有​​的iterator_traits废话。 STL使用编译时模板调度而不是运行时动态调度,因此您的迭代器不仅要模板化输入枚举器的value_type,还要模板化特定类型的输入枚举器。

当我尝试在STL中编写map-join迭代器时,甚至不让我开始。

通过查看其他人编写的代码,我得出的结论是,未使用Boost的STL很少用于集合和排序以外的任何其他内容。

我的近端观察是:

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

    1. STL代码似乎并不简洁。在编写STL代码时,我的目的是编写简洁的代码吗? (我的意思是,不简洁,通常涉及非常长的类型标识符)
    2. Boost似乎是在STL中编写算法的近似要求。不允许使用Boost的人做什么?

1 个答案:

答案 0 :(得分:2)

你的一些问题对我来说并没有多大意义。例如,您谈到必须处理“enumerator_traits”。我不太确定你在谈论什么。也许你的意思是iterator_traits?我不记得曾经使用过任何名为“enumerator_trait”的东西,在C ++标准中也找不到这样的东西。

iterator_traits至少存在,但它们是我很少“混乱”的东西。我周围都知道他们的存在,但仅仅是那个。我编写了大量的迭代器和算法,而没有对任何特定的iterator_traits做任何特定的事情。

让我们来看看创建一个新集合的具体问题,该集合是另一个集合的排序版本。这在很多方面都相当容易。 std::partial_sort_copy当然可以做到:

#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());

然而,最后这种情况通常会使代码缩短效率。在许多(大多数?)情况下,这不是一个问题,但如果你发现它太慢,可以很容易地获得更快的替代品。