关联容器,是比较函数不是元素类型的一部分?

时间:2018-03-26 17:01:11

标签: c++ templates

我认为,可以传递给关联容器模板的comparsion函数,如std::setstd::multiset,不是实例化容器的实际element type的一部分 - 类型?

#include <iostream>
#include <set>
#include "Sales_data_ex1119.hpp"
using namespace std;

bool compare_isbn(const Sales_data& lhs, const Sales_data& rhs) {
    return lhs.isbn() < rhs.isbn();
}

int main() {
    using cmp_func = bool (*)(const Sales_data& lhs, const Sales_data& rhs);
    multiset<Sales_data, cmp_func> bookstore(&compare_isbn);
    Sales_data foo("978", 2, 22.22);
    Sales_data foo2("978", 2, 22.22);
    Sales_data bar("979", 3, 22.22);
    Sales_data baz("980", 2, 22.22);

    bookstore.insert(foo);
    bookstore.insert(foo2);
    bookstore.insert(bar);
    bookstore.insert(baz);

    // comparsion function is not part of element type?
    multiset<Sales_data>::iterator it = bookstore.begin();
    while (it != bookstore.end()) {
        print(cout, *it++);
        cout << "\n";
    }
    cout << "\n";

    // but the comparsion function can be applied also
    multiset<Sales_data, cmp_func>::iterator it2 = bookstore.begin();
    while (it2 != bookstore.end()) {
        print(cout, *it2++);
        cout << "\n";
    }   

    return 0;
}

两个定义itit2都可以在GCC 7中编译并运行正常。对我而言,key_type定义为Sales_data和{{1} } key_typestd::setstd::multiset 如果在定义中看到很多people using比较函数,这可能只是更加明显但不是必需的。

由于

1 个答案:

答案 0 :(得分:4)

  

我认为,comparsion函数可以传递给关联容器的模板,比如std :: set或std :: multiset,它不是实例化容器类型的实际元素类型的一部分吗?

multiset<Key,Compare,Allocator>中迭代器唯一完全可靠的类型是multiset<Key,Compare,Allocator>::iterator

现在,因为多集中的每个节点都不真正需要排序顺序或分配器来完成它的工作,并且因为库编写者更喜欢避免重复,所以很有可能在标准库的某处有一个迭代器类模板,它在所有(多)(set | map)类之间共享,并且仅取决于元素类型。

但如果是这种情况,那么它是一个实现细节,是不可移植的,可能会有所变化。所以,这个:

multiset<Sales_data, cmp_func> bookstore(&compare_isbn);
multiset<Sales_data>::iterator it = bookstore.begin();

目前可能会有效。但是对于另一个编译器或库实现来说拒绝它是完全合法的。

无论如何,即使没有包含Compare(和Allocator!)类型参数,写出整个内容也非常繁琐。只需使用

auto it = bookstore.begin()

忘了整件事。或者,更好的是:

for (auto &sale : bookstore) {

或在您的特定情况下,编写流插入运算符并使用

copy(begin(bookstore), end(bookstore),
     ostream_iterator<Sales_data>(cout, "\n"));