从C++ 14开始,总是更喜欢设置<T,less <>>来设置<T>?

xml*_*lmx 29 c++ convention performance standards 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
}
Run Code Online (Sandbox Code Playgroud)

那么,它应该是一个规则:

总是喜欢 set<T, less<>> set<T> ,因为C++ 14

T.C*_*.C. 19

找到一个反例是微不足道的:

#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
}
Run Code Online (Sandbox Code Playgroud)

  • ......它不起作用的原因是什么?是因为标准不要求(禁止?)`basic_string`上的`operator <`是一个非成员函数,因此演绎失败了吗?如果`basic_string`的`operator <`被定义为朋友(非模板)函数,它会工作吗? (2认同)
  • @dyp是的,扣除失败,因为它是非成员函数模板(与`basic_string_view`不同,没有"足够的额外过载"规则).是的,一个朋友的非模板函数可以使这个工作(每个比较一个临时字符串,就像你的`stupid_string`). (2认同)

dyp*_*dyp 10

使用时可能存在性能下降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");
}
Run Code Online (Sandbox Code Playgroud)

这里,在operator<执行的算法中的应用s.find将字符文字转换为stupid_string隐式.每次比较都会发生这种情况!现场演示

我知道有一个案例,在生产代码中发生了类似的事情,并且使用了不符合要求的C++ 03 StdLib实现.


顺便说一下,异构查找通道的主要原因less<>是选择加入; 见N3657:

Stephan T. Lavavej建议保留现有行为和允许异构查找的两个问题都可以通过使容器检测比较对象何时接受异构参数并且仅使用模板版本有条件地重载当前查找函数来解决.

  • 这基本上是异构查找选择加入的原因. (2认同)