简体   繁体   English

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

[英]Why does the C++ standard not change std::set to use std::less<> as its default template argument?

#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); is more efficient than v1.contains("abc"s);v1.contains("abc"s);更有效, because it needn't to construct a string object. , 因为它不需要构造一个字符串 object。

However, the C++ standard uses std::less<T> , rather than std::less<> , as std::set 's default template argument.但是,C++ 标准使用std::less<T>而不是std::less<>作为std::set的默认模板参数。 So, CTAD (Class Template Argument Deduction) doesn't work on std::less<> , I have to write ugly std::set<std::string, std::less<>>{"abc"s} , rather than std::set{"abc"s} .所以, CTAD(类模板参数推导)std::less<>上不起作用,我必须写丑陋的std::set<std::string, std::less<>>{"abc"s} ,而不是std::set{"abc"s}

Why does the C++ standard not change std::set to use std::less<> as its default template argument?为什么 C++ 标准不更改std::set以使用std::less<>作为其默认模板参数? Just for backward compatibility?只是为了向后兼容?

Moving from std::set<T, std::less<T>> to std::set<T, std::less<>> can make key-finding algorithms more efficient, if the search-key never has to be converted.std::set<T, std::less<T>>移动到std::set<T, std::less<>>可以使关键字查找算法更有效,如果搜索关键字不必转换。

Conversely, it can make them less efficient if the conversion occurrs on every call to the comparator, instead of once in the caller on starting the algorithm.相反,如果转换发生在每次调用比较器时,而不是在调用者启动算法时发生一次,它可能会降低它们的效率。 Those conversions can be quite expensive.这些转换可能非常昂贵。

Especially if the conversion from search-key to T is lossy, there isn't even a guarantee both would yield the same result!特别是如果从 search-key 到T的转换是有损的,甚至不能保证两者都会产生相同的结果!

For these reasons, such a change is not a straight upgrade, but a breaking change.由于这些原因,这样的改变不是直接的升级,而是突破性的改变。 And the committee is quite loath to introduce those.委员会非常不愿意介绍这些。

Why does the C++ standard not change std::set to use std::less<> as its default template argument?为什么 C++ 标准不更改std::set以使用std::less<>作为其默认模板参数? Just for backward compatibility?只是为了向后兼容?

This would be an ABI break.这将是 ABI 中断。

// a.cpp
void f(std::set<int> const&) { ... }

// b.cpp
void g() {
    std::set<int> s = /* ... */;
    f(s);
}

If a.cpp is compiled on C++11, f takes a std::set<int, std::less<int>> .如果a.cpp在 C++11 上编译,则f采用std::set<int, std::less<int>>

If the standard library changed the default comparison from std::less<T> to std::less<void> in C++14 ( N3421 was only written in 2012), and b.cpp was compiled on C++14, then s would be a std::set<int, std::less<void>> .如果标准库将 C++14 中的默认比较从std::less<T>更改为std::less<void>N3421仅在 2012 年编写),并且b.cpp在 C++14 上编译,则s将是std::set<int, std::less<void>> And now we fail to link.现在我们无法链接。

My guess is because they thought it wasn't so great improvement to break backward compatibility.我的猜测是因为他们认为打破向后兼容性并不是很大的改进。

Another reason is because std::set with std::less<Key> existed even before C++11 (starting from C++03 I guess) and std::less<> appeared only in C++14.另一个原因是因为带有std::less<Key>std::set甚至在 C++11 之前就已经存在(我猜是从 C++03 开始),而std::less<>仅出现在 C++14 中。 So if they move to std::set with std::less<> then you have to force C++14 when using set, or you have to make two kinds of sets - one for C++03 and one for C++14.因此,如果他们使用std::less<>移动到std::set ,那么您必须在使用 set 时强制 C++14 ,或者您必须制作两种集合 - 一种用于 C++03,一种用于 C++14。

Also if you start from C++14 making set being std::less<>-based then your pre-C++14 code will start to behave differently sometimes.此外,如果您从 C++14 开始设置基于 std::less<> 的设置,那么您的 C++14 之前的代码有时会开始表现不同。 For example your code relied on calling Key's constructor for some reason when adding to set, then suddenly if you add option -std=c++14 your old code starts doing other things.例如,您的代码在添加到 set 时出于某种原因依赖于调用 Key 的构造函数,然后突然如果您添加选项-std=c++14您的旧代码开始执行其他操作。

Usually STD people make such changes that switching from C++11 to C++14 doesn't break code's behaviour.通常 STD 人会做出这样的改变,从 C++11 切换到 C++14 不会破坏代码的行为。 Only downswitching from C++14 to C++11 can break something(usually non-compiling).只有从 C++14 向下切换到 C++11 才能破坏某些东西(通常是非编译)。 In other words it is backward compatibility breaking change to use std::less<>.换句话说,使用 std::less<> 是向后兼容的破坏性更改。 Such changes are usually only done by introducing new class name for such specializations.此类更改通常仅通过为此类专业化引入新的 class 名称来完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++覆盖特定数据类型的std :: set的默认小于参数 - C++ overriding default less than argument for std::set for a particular data type 为什么要使用std :: less作为默认函子来比较std :: map和std :: set中的键? - Why use std::less as the default functor to compare keys in std::map and std::set? 如何在C ++中为std :: list参数设置默认值? - How to set a default value for std::list argument in C++? 为什么C ++标准为std :: bitset :: reference指定了析构函数? - Why does the C++ standard specifies a destructor for std::bitset::reference? 当模板参数要求 std::less 时,编译器如何在 std::set 中使用 T::operator&lt;<T> ? - How does a compiler use T::operator< in std::set when the template parameter asks for std::less<T>? C ++:&(std :: cout)作为模板参数 - C++ : &(std::cout) as template argument std :: pair作为模板 <class> 争论? C ++ - std::pair as a template<class> argument? C++ 使用std :: greater或std :: less作为参数的参数 - Parameter to use std::greater or std::less as argument 为什么C ++标准允许std :: max_align_t和__STDCPP_DEFAULT_NEW_ALIGNMENT__不一致? - Why does the C++ standard allow std::max_align_t and __STDCPP_DEFAULT_NEW_ALIGNMENT__ to be inconsistent? 为什么std :: less是一个类模板? - Why is std::less a class template?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM