为什么C ++容器中的方法没有统一的签名

时间:2018-12-26 11:41:51

标签: c++ stl stdvector c++-standard-library stdset

我想编写一种将项目添加到容器的方法,而不管该容器的类型如何。为了清楚表明我的意图,我将附加一个Java代码段,以执行相同的操作。

public static <T> void add(Collection<T> collection, T element){
    collection.add(element);
}

public static void main (String[] args) {
    Set<Integer> s = new TreeSet<>();
    List<Integer> l = new ArrayList<>();
    add(s, 1);
    add(l, 1);
}

这在Java中是可能的,因为所有集合都实现一个公共接口。假设出于性能原因,C ++设计人员决定在容器中不使用虚拟方法。但是,恕我直言,考虑c ++模板的工作方式,为vector::insert使用别名方法vector::push_back是有意义的。缺少该方法是以下代码无法编译的原因。

#include <vector>
#include <set>


template<typename T, typename E>
void insert(T container, E element) {
    container.insert(element);
}

int main() {
    std::vector<int> v;
    std::set<int> s;
    insert(v, 1);
    insert(s, 1);
    return 0;
} 

可以有很多解决此问题的方法。但是我想知道为什么C ++的设计者不关心这个问题,或者不在随后的语言版本中添加它的原因吗?这是故意做的吗?

1 个答案:

答案 0 :(得分:1)

在使用标准容器的情况下,您可以考虑将插入和擦除操作视为类似的接口。

并非所有容器都保持相同,因为这会带来额外的性能/内存损失,甚至在某些容器的情况下也没有意义。例如,forward_list :: insert_after代替插入,因为在那儿插入没有意义。

另一方面,

限制界面(如您建议使用带有一个参数的vector :: insert)尚不清楚。实际上,它将引入一些与容器类型结构无关的行为。也许您希望您的一个参数插入将数据放在向量前面,而不是后面?那么不要争论向量,在双端队列情况下应该如何工作?

扩展接口也没有意义-在使用stack或forward_list的情况下,如何使用两个参数插入?

还值得一提的是C ++ std为容器和算法提供了最少的实现。假设您可以自行扩展此最小实现。

所以我会说:

  1. 性能
  2. 界面/容器操作清晰
  3. 仅提供最低限度的实施,没有不必要的假设