首页 > 解决方案 > 为什么 C++ 标准不更改 std::set 以使用 std::less<> 作为其默认模板参数?

问题描述

#include <set>
#include <string>
#include <string_view>

using namespace std::literals;

int main()
{
    auto v1 = std::set<std::string, std::less<>>{"abc"s};
    v1.contains("abc"s);  // ok
    v1.contains("abc"sv); // ok
    
    auto v2 = std::set{"abc"s};
    v2.contains("abc"s);  // ok
    v2.contains("abc"sv); // error
}

v1.contains("abc"sv);比 更有效v1.contains("abc"s);,因为它不需要构造字符串对象。

但是,C++ 标准使用std::less<T>,而不是std::less<>,作为std::set默认模板参数。所以,CTAD(Class Template Argument Deduction)不起作用std::less<>,我必须写丑陋std::set<std::string, std::less<>>{"abc"s}的,而不是std::set{"abc"s}

为什么 C++ 标准没有更改std::setstd::less<>用作其默认模板参数?只是为了向后兼容?

标签: c++c++14standardsc++20backwards-compatibility

解决方案


如果不必转换搜索关键字,则从std::set<T, std::less<T>>到移动std::set<T, std::less<>>可以使关键字查找算法更有效。

相反,如果转换发生在每次调用比较器时,而不是在调用者启动算法时发生一次,它可能会降低它们的效率。这些转换可能非常昂贵。

特别是如果从搜索键到的转换T是有损的,甚至不能保证两者都会产生相同的结果!

由于这些原因,这样的改变不是直接的升级,而是突破性的改变。委员会非常不愿意介绍这些。


推荐阅读