Search code examples
c++c++14standardsc++20backwards-compatibility

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);, because it needn't to construct a string object.

However, the C++ standard uses std::less<T>, rather than std::less<>, as std::set's default template argument. 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}.

Why does the C++ standard not change std::set to use std::less<> as its default template argument? Just for backward compatibility?


Solution

  • 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. 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.

    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. 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.

    Usually STD people make such changes that switching from C++11 to C++14 doesn't break code's behaviour. Only downswitching from C++14 to C++11 can break something(usually non-compiling). In other words it is backward compatibility breaking change to use std::less<>. Such changes are usually only done by introducing new class name for such specializations.