你如何编写一个operator()或者比trivalue-compare-function更少的函子

Gri*_*ngo 8 c++ stl

为结构编写运算符<()似乎比编写经典的trivalue比较更清晰.

例如,对以下内容进行排序

struct S {
    int val;
};
Run Code Online (Sandbox Code Playgroud)

你可以写一个运算符<()

bool operator< ( const S &l, const S &r ) {
     return l.val < r.val;
}
Run Code Online (Sandbox Code Playgroud)

或者,三值函数(通常以下列方式)

int compare( const S &l, const S &r ) {
    if( r.val > l.val ) return 1;
    if( r.val < l.val ) return -1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

前者更清晰,因此可以说代码质量更好.后者迫使你想到3个案例,这使代码变得复杂.

但是这个想法在更复杂的结构中有点欺骗:

struct S {
    int x;
    int y;
};
Run Code Online (Sandbox Code Playgroud)

以下是明确的,并且begginners倾向于这样写

bool operator< ( const S &l, const S &r ) {
     if( l.x < r.x ) return true;
     if( l.y < r.y ) return true;
     return false;
}
Run Code Online (Sandbox Code Playgroud)

但这是错的!你无法正确排序!

并且认为你实际上必须这样写它需要一些时间

bool operator< ( const S &l, const S &r ) {
     if( l.x < r.x ) return true;
     if( l.x > r.x ) return false;
     if( l.y < r.y ) return true;
     if( l.y > r.y ) return false;
     return false;
}
Run Code Online (Sandbox Code Playgroud)

为了它正常工作.

你可以,并且你是否以更好/更清晰的方式编写这种比较函数? 旧的trivalue比较函数至少"强迫"你考虑>,<和==情况.

MSN*_*MSN 5

如果我不关心性能或编译器,我倾向于使用:

return make_tuple(l.x, l.y, ...) < make_tuple(r.x, r.y, ...);
Run Code Online (Sandbox Code Playgroud)

而副本版本的价格略低:

return tie(cref(l.x), cref(l.y), ...) < tie(cref(r.x), cref(r.y), ...);
Run Code Online (Sandbox Code Playgroud)

顺便提一下,第二个版本也适用于左值.

  • 有趣的想法.但是不会'返回领带(lx,ly,...)<tie(rx,ry,...);`避免副本?(我假设这会创建引用元组). (2认同)

Let*_*_Be 3

问题是,如果您使用以下命令自动生成所有运算符,则只需声明一个三值比较函数即可:http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick