为什么STL设置比较器仅通过模板指定?

MK.*_*MK. 3 c++ stl

向std :: set容器提供自定义比较器的唯一方法是通过模板特化.这意味着比较器细节将泄漏给该组的所有用户.有没有办法绕过它以及为什么做出如此奇怪的决定选择?我不应该有一个方法可以返回一个按我喜欢的方式订购的一套,但没有人知道订购的是什么吗?

Die*_*ühl 5

对于许多用途,默认的比较选择,即使用std::less<T>哪种用途a < b非常有效.此比较不执行任何动态分派,这将允许在不影响类型的情况下选择顺序,因为动态分派可能会导致性能下降.添加动态调度肯定会在界面定义时导致性能下降,我认为它仍然是真的,不太可能完全消失.

如果您想在不影响您可以使用的类型的情况下选择订单std::function<bool(T const&, T const&)>(或者std::function<bool(T, T)>如果T碰巧是一种便宜的复制类型,如内置类型).在这种情况下,您需要将比较对象指定为构造函数参数.例如:

std::set<int, std::function<bool(int, int)>> values{std::less<int>()};
Run Code Online (Sandbox Code Playgroud)

请注意,上面的代码使用curlies,否则它将是一个函数声明而不是一个对象定义.另请注意,将a分配给std:set<int, std::function<bool(int, int)>>具有不同比较功能的另一个将不起作用:代码将编译但是赋值将创建一个错误排序的集合.例如:

#include <functional>
#include <iostream>
#include <set>

int main() {
    std::set<int, std::function<bool(int, int)>> values1{std::less<int>()};
    values1.insert(1);
    values1.insert(2);
    values1.insert(3);
    std::set<int, std::function<bool(int, int)>> values2{std::greater<int>()};
    values2 = values1;
    for (auto v: values2) {
        std::cout << v << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

这将按升序打印值,尽管它应按降序打印.