自 C++14 以来,总是更喜欢 set<T, less<>> 而不是 set<T> ?
Always prefer set<T, less<>> to set<T> since C++14?
#include <set>
#include <string>
#include <string_view>
using namespace std;
int main()
{
string_view key = "hello";
set<string> coll1;
coll1.find(key); // error
set<string, less<>> coll2;
coll2.find(key); // ok since C++14
}
那么,是不是应该规定一下:
从 C++14?
找反例很简单:
#include <set>
#include <string>
using namespace std;
struct converts_to_string {
operator string() const { return ""; }
};
int main()
{
converts_to_string key;
set<string> coll1;
coll1.find(key); // OK
set<string, less<>> coll2;
coll2.find(key); // error
}
使用 associative_container<T, less<>>
时可能会出现性能下降:考虑像
这样的类型
#include <iostream>
#include <set>
#include <string>
struct stupid_string
{
stupid_string(char const* s)
: s(s)
{ std::cout << "copy\n"; }
stupid_string(char const* s, int) // silent
: s(s)
{}
friend bool operator<(stupid_string const& lhs, stupid_string const& rhs);
private:
std::string s;
};
bool operator<(stupid_string const& lhs, stupid_string const& rhs) {
return lhs.s < rhs.s;
}
int main() {
std::set<stupid_string, std::less<>> s;
s.emplace("hello", 0);
s.emplace("world", 0);
s.emplace("foobar", 0);
std::cout << "find\n";
(void)s.find("test");
}
此处,operator<
在 s.find
执行的算法中的应用会将字符文字隐式转换为 stupid_string
。每次执行比较都会发生这种情况! Live demo
我知道一个案例,在生产代码中发生了类似的事情,使用了不符合标准的 C++03 StdLib 实现。
顺便说一下,这是选择通过 less<>
进行异构查找的主要原因;见 N3657:
Stephan T. Lavavej suggested that the two problems of preserving
existing behaviour and allowing heterogeneous lookups could both be
solved by making the containers detect when the comparison object
accepts heterogeneous arguments and only conditionally overloading the
current lookup functions with template versions.
#include <set>
#include <string>
#include <string_view>
using namespace std;
int main()
{
string_view key = "hello";
set<string> coll1;
coll1.find(key); // error
set<string, less<>> coll2;
coll2.find(key); // ok since C++14
}
那么,是不是应该规定一下:
从 C++14?
找反例很简单:
#include <set>
#include <string>
using namespace std;
struct converts_to_string {
operator string() const { return ""; }
};
int main()
{
converts_to_string key;
set<string> coll1;
coll1.find(key); // OK
set<string, less<>> coll2;
coll2.find(key); // error
}
使用 associative_container<T, less<>>
时可能会出现性能下降:考虑像
#include <iostream>
#include <set>
#include <string>
struct stupid_string
{
stupid_string(char const* s)
: s(s)
{ std::cout << "copy\n"; }
stupid_string(char const* s, int) // silent
: s(s)
{}
friend bool operator<(stupid_string const& lhs, stupid_string const& rhs);
private:
std::string s;
};
bool operator<(stupid_string const& lhs, stupid_string const& rhs) {
return lhs.s < rhs.s;
}
int main() {
std::set<stupid_string, std::less<>> s;
s.emplace("hello", 0);
s.emplace("world", 0);
s.emplace("foobar", 0);
std::cout << "find\n";
(void)s.find("test");
}
此处,operator<
在 s.find
执行的算法中的应用会将字符文字隐式转换为 stupid_string
。每次执行比较都会发生这种情况! Live demo
我知道一个案例,在生产代码中发生了类似的事情,使用了不符合标准的 C++03 StdLib 实现。
顺便说一下,这是选择通过 less<>
进行异构查找的主要原因;见 N3657:
Stephan T. Lavavej suggested that the two problems of preserving existing behaviour and allowing heterogeneous lookups could both be solved by making the containers detect when the comparison object accepts heterogeneous arguments and only conditionally overloading the current lookup functions with template versions.