如何在C++ std :: set中放置看似无法比较的对象?

Sta*_*ked 2 c++ algorithm

假设我想将标识服务器的对象放入stl中set.然后我必须确保我也operator<为这些对象实现,否则我会遇到编译器错误:

struct ServerID
{
  std::string name; // name of the server
  int port;
};

std::set<ServerID> servers; // compiler error, no operator< defined
Run Code Online (Sandbox Code Playgroud)

这只是我想要使对象具有可比性的常见问题的一个例子.

我目前的解决方案通常是这样的:

bool operator< (const ServerID & lhs, const ServerID & rhs)
{
  if (lhs.name != rhs.name)
  {
    return lhs.name < rhs.name;
  }
  else
  {
    return lhs.port < rhs.port;
  }
}
Run Code Online (Sandbox Code Playgroud)

这只是我发现自己的解决方案.但我怀疑这个问题也可能在计算机科学中得到认可.所以,如果我很幸运,有一个更好的解决方案.任何人都可以向我暗示吗?

Dav*_*eas 14

我建议不要将它实现为operator <,以避免可能的混淆,而是将order函数作为参数传递给std :: set template参数.

struct server
{
   std::string name;
   int port;
};
struct name_then_port : public std::binary_function<server,server,bool>
{
   bool operator()( server const & lhs, server const & rhs ) {
      // using litb approach (more efficient as it does not call both < and == on strings:
      int cmp = lhs.name.compare(rhs.name);
      return ( cmp < 0 ) || ((cmp==0) && ( lhs.port < rhs.port));
   }
};
struct port_then_name : public std::binary_function<server,server,bool>
{
   bool operator()( server const & lhs, server const & rhs ) {
      return (lhs.port < rhs.port) || ((lhs.port==rhs.port) && (lhs.name<rhs.name));
   }
};
int main()
{
   std::set< server, name_then_port > servers; // or:
   std::set< server, port_then_name > servers2;
}
Run Code Online (Sandbox Code Playgroud)

关于此问题是否已经确定之前的问题,它有.一般解决方案正是您发布的:词典顺序.虽然这个术语通常被称为字符串排序,但排序是相同的:取第一个元素,比较它是否定义一个顺序采用下一个数据元素并迭代.