C++ 用正确的方法或设计模式来简化类中的'operatorX'函数,以便按给定顺序比较相同类型的属性?

C++ 用正确的方法或设计模式来简化类中的'operatorX'函数,以便按给定顺序比较相同类型的属性?,c++,c++11,design-patterns,comparison,operators,C++,C++11,Design Patterns,Comparison,Operators,过去,我通过编写一个以比较函数为参数的helper函数,减少了数据类型类的operator=函数中的重复 简化后,此类类如下所示: class Foo { public: bool comparison(const Foo &other, std::function<bool(int a, int b)> compFn) { if (_a == other._a) { if (_b == other._b) {

过去,我通过编写一个以比较函数为参数的helper函数,减少了数据类型类的
operator=
函数中的重复

简化后,此类类如下所示:

class Foo {
public:
    bool comparison(const Foo &other, std::function<bool(int a, int b)> compFn) {
        if (_a == other._a) {
            if (_b == other._b) {
                 return compFn(_c, other._c);
            }
            return compFn(_b, other._b);
        }
        return compFn(_a, other._a);
    }
    bool operator<(const Foo &other) const {
        return comparison(other, [](int a, int b){return a<b;})
    }
    bool operator<=(const Foo &other) const {
        return comparison(other, [](int a, int b){return a<=b;})
    }
    bool operator>(const Foo &other) const {
        return comparison(other, [](int a, int b){return a>b;})
    }
    bool operator>=(const Foo &other) const {
        return comparison(other, [](int a, int b){return a>=b;})
    }
private:
    int _a;
    int _b;
    int _c;
};
class-Foo{
公众:
布尔比较(常量Foo和其他,标准::函数compFn){
如果(_a==其他._a){
如果(_b==其他._b){
返回compFn(_c,其他._c);
}
返回compFn(_b,其他._b);
}
返回compFn(_a,其他._a);
}
布尔运算符=b;})
}
私人:
国际组织;
int_b;
国际奥委会;
};
真正的类使用复杂的数据类型,但原理保持不变。“比较少”或“比较大”是按给定顺序对多个属性进行的比较

使用
比较
函数,我可以随时更改此顺序,只需重写单个函数即可。此外,逻辑是在一个点上,而不是在四个地方重复

是否有既定的设计模式来涵盖这种情况?

我意识到已经有了比较对象,比如
std::less
。但我找不到一个简单的方法来使用它们,而不是显示的解决方案


显示的解决方案是否可以使用其他语言功能或标准库进一步简化?

我想您需要调度到c++2x中的操作员太空船“”三方真名

当然,这将是正确的模式使用,因为当它到达这里时,您可以迁移到它

基本上,如果参数相等,则返回0;如果参数比较“少”,则返回-1;如果参数比较“大”,则返回+1。有关示例,请参见strcmp()


您可以选择使用=和>,然后所有其他操作符调用,或者直接实现并让/all/other操作符简单地调用它。

您需要调度到c++2x的操作符太空船“”,我想。:-)三方真名

当然,这将是正确的模式使用,因为当它到达这里时,您可以迁移到它

基本上,如果参数相等,则返回0;如果参数比较“少”,则返回-1;如果参数比较“大”,则返回+1。有关示例,请参见strcmp()


您可以选择使用=和>,然后所有其他操作符调用,或者直接实现并让/all/other操作符调用它。

您的实现对我来说有点复杂

我将尝试使用以下方法解决此问题:

class Foo {
public:    
    bool operator<(const Foo &other) const {
        return std::tie(_a, _b, _c) <
            std::tie(other._a, other._b, other._c);
    }

    bool operator<=(const Foo &other) const {
        return std::tie(_a, _b, _c) <=
            std::tie(other._a, other._b, other._c);
    }

    bool operator>(const Foo &other) const {
        return !(*this <= other);
    }

    bool operator>=(const Foo &other) const {
        return !(*this < other);
    }

private:
    int _a;
    int _b;
    int _c;
};
class-Foo{
公众:

布尔运算符您的实现对我来说有点复杂

我将尝试使用以下方法解决此问题:

class Foo {
public:    
    bool operator<(const Foo &other) const {
        return std::tie(_a, _b, _c) <
            std::tie(other._a, other._b, other._c);
    }

    bool operator<=(const Foo &other) const {
        return std::tie(_a, _b, _c) <=
            std::tie(other._a, other._b, other._c);
    }

    bool operator>(const Foo &other) const {
        return !(*this <= other);
    }

    bool operator>=(const Foo &other) const {
        return !(*this < other);
    }

private:
    int _a;
    int _b;
    int _c;
};
class-Foo{
公众:

bool操作符您可以使用奇怪的重复模板模式Barton Nackman技巧结合使用。 您只需要在类中定义一个比较函数,该函数返回:

< 0   if a < b
> 0   if a > b
== 0  if a == b
<0如果a如果a>b,则为0
如果a==b,则=0
实例化类模板时,类内友元定义将生成运算符定义

没有CRTP的正常运行时多态性也可以工作

您可以根据需要更改Cmp(…)中的比较逻辑,并且运算符函数运行良好

#include <iostream>
#include <iomanip>
#include <tuple>

using namespace std;

template<typename T>
struct Comparable {
  friend bool operator==(const T& lft, const T& rgt) {
    return lft.Cmp(rgt) == 0;
  }

  friend bool operator<(const T& lft, const T& rgt) {
    return lft.Cmp(rgt) < 0;
  }

  friend bool operator>(const T& lft, const T& rgt) {
    return lft.Cmp(rgt) > 0;
  }

  friend bool operator!=(const T& lft, const T& rgt) {
    return !operator==(lft, rgt);
  }

  friend bool operator<=(const T& lft, const T& rgt) {
    return !operator>(lft, rgt);
  }

  friend bool operator>=(const T& lft, const T& rgt) {
    return !operator<(lft, rgt);
  }
};

class Foo : public Comparable<Foo> {

  private:
    static int cmpMode_;

  public:
    static void SetDefaultComparator() { cmpMode_ = 1; }
    static void SetInvertedComparator() { cmpMode_ = -1; }

  public:
    Foo() : a_{0}, b_{0}, c_{0} {}
    Foo(int a, int b, int c) : a_{a}, b_{b}, c_{c} {}

    // return  < 0   if lhs < rhs
    // return == 0   if lhs == rhs
    // return > 0    if lhs > rhs
    int Cmp(const Foo& rhs) const {
      auto t1 = std::tie(a_, b_, c_);
      auto t2 = std::tie(rhs.a_, rhs.b_, rhs.c_);
      auto cmp = t1 < t2 ? -1 : (t1 > t2 ? 1 : 0);
      return cmpMode_ * cmp;
    }

  private:
    int a_;
    int b_;
    int c_;
};  // Foo

int Foo::cmpMode_ = 1;

int main() {

  Foo f1{1,1,1};
  Foo f2{1,1,1};
  Foo f3{1,1,2};
  Foo f4{1,2,1};

  Foo::SetDefaultComparator();

  cout << endl << "Using default comparator: " << endl;
  cout << boolalpha
    << "f1 == f2 ? " << (f1 == f2) << endl
    << "f1 != f2 ? " << (f1 != f2) << endl
    << "f2 < f3 ? " << (f2 < f3) << endl
    << "f2 <= f3 ? " << (f2 <= f3) << endl
    << "f3 > f4 ? " << (f3 > f4) << endl
    << "f3 >= f4 ? " << (f3 >= f4) << endl
    << "f4 > f3 ? " << (f4 >= f4) << endl;


  Foo::SetInvertedComparator();

  cout << endl << "Using inverted comparator: " << endl;
  cout << boolalpha
    << "f1 == f2 ? " << (f1 == f2) << endl
    << "f1 != f2 ? " << (f1 != f2) << endl
    << "f2 < f3 ? " << (f2 < f3) << endl
    << "f2 <= f3 ? " << (f2 <= f3) << endl
    << "f3 > f4 ? " << (f3 > f4) << endl
    << "f3 >= f4 ? " << (f3 >= f4) << endl
    << "f4 > f3 ? " << (f4 >= f4) << endl;
}
#包括
#包括
#包括
使用名称空间std;
模板
结构可比{
友元布尔运算符==(常数T&lft,常数T&rgt){
返回lft.Cmp(rgt)==0;
}
friend bool运算符(常数T&lft、常数T&rgt){
返回lft.Cmp(rgt)>0;
}
友元布尔运算符!=(常数T&lft,常数T&rgt){
return!运算符==(lft,rgt);
}
friendbool算子(lft,rgt);
}
友元布尔运算符>=(常数T&lft、常数T&rgt){
返回!如果左侧>右侧,则运算符0
内部凸轮轴位置(常开和右开)常开{
自动t1=std::tie(a、b、c);
自动t2=std::tie(rhs.a_、rhs.b_、rhs.c_);
自动cmp=t1t2-1:0);
返回cmpMode_*cmp;
}
私人:
INTA_;
int b_;
国际货币基金组织;
};//福
intfoo::cmpMode_u2;=1;
int main(){
Foo f1{1,1,1};
Foo f2{1,1,1};
Foo f3{1,1,2};
Foo f4{1,2,1};
Foo::SetDefaultComparator();

cout您可以使用奇怪的重复模板模式Barton Nackman技巧相结合。 您只需要在类中定义一个比较函数,该函数返回:

< 0   if a < b
> 0   if a > b
== 0  if a == b
<0如果a如果a>b,则为0
如果a==b,则=0
实例化类模板时,类内友元定义将生成运算符定义

没有CRTP的正常运行时多态性也可以工作

您可以根据需要更改Cmp(…)中的比较逻辑,并且运算符函数运行良好

#include <iostream>
#include <iomanip>
#include <tuple>

using namespace std;

template<typename T>
struct Comparable {
  friend bool operator==(const T& lft, const T& rgt) {
    return lft.Cmp(rgt) == 0;
  }

  friend bool operator<(const T& lft, const T& rgt) {
    return lft.Cmp(rgt) < 0;
  }

  friend bool operator>(const T& lft, const T& rgt) {
    return lft.Cmp(rgt) > 0;
  }

  friend bool operator!=(const T& lft, const T& rgt) {
    return !operator==(lft, rgt);
  }

  friend bool operator<=(const T& lft, const T& rgt) {
    return !operator>(lft, rgt);
  }

  friend bool operator>=(const T& lft, const T& rgt) {
    return !operator<(lft, rgt);
  }
};

class Foo : public Comparable<Foo> {

  private:
    static int cmpMode_;

  public:
    static void SetDefaultComparator() { cmpMode_ = 1; }
    static void SetInvertedComparator() { cmpMode_ = -1; }

  public:
    Foo() : a_{0}, b_{0}, c_{0} {}
    Foo(int a, int b, int c) : a_{a}, b_{b}, c_{c} {}

    // return  < 0   if lhs < rhs
    // return == 0   if lhs == rhs
    // return > 0    if lhs > rhs
    int Cmp(const Foo& rhs) const {
      auto t1 = std::tie(a_, b_, c_);
      auto t2 = std::tie(rhs.a_, rhs.b_, rhs.c_);
      auto cmp = t1 < t2 ? -1 : (t1 > t2 ? 1 : 0);
      return cmpMode_ * cmp;
    }

  private:
    int a_;
    int b_;
    int c_;
};  // Foo

int Foo::cmpMode_ = 1;

int main() {

  Foo f1{1,1,1};
  Foo f2{1,1,1};
  Foo f3{1,1,2};
  Foo f4{1,2,1};

  Foo::SetDefaultComparator();

  cout << endl << "Using default comparator: " << endl;
  cout << boolalpha
    << "f1 == f2 ? " << (f1 == f2) << endl
    << "f1 != f2 ? " << (f1 != f2) << endl
    << "f2 < f3 ? " << (f2 < f3) << endl
    << "f2 <= f3 ? " << (f2 <= f3) << endl
    << "f3 > f4 ? " << (f3 > f4) << endl
    << "f3 >= f4 ? " << (f3 >= f4) << endl
    << "f4 > f3 ? " << (f4 >= f4) << endl;


  Foo::SetInvertedComparator();

  cout << endl << "Using inverted comparator: " << endl;
  cout << boolalpha
    << "f1 == f2 ? " << (f1 == f2) << endl
    << "f1 != f2 ? " << (f1 != f2) << endl
    << "f2 < f3 ? " << (f2 < f3) << endl
    << "f2 <= f3 ? " << (f2 <= f3) << endl
    << "f3 > f4 ? " << (f3 > f4) << endl
    << "f3 >= f4 ? " << (f3 >= f4) << endl
    << "f4 > f3 ? " << (f4 >= f4) << endl;
}
#包括
#包括
#包括
使用名称空间std;
模板
结构可比{
友元布尔运算符==(常数T&lft,常数T&rgt){
返回lft.Cmp(rgt)==0;
}
friend bool运算符(常数T&lft、常数T&rgt){
返回lft.Cmp(rgt)>0;
}
友元布尔运算符!=(常数T&lft,常数T&rgt){
return!运算符==(lft,rgt);
}
friendbool算子(lft,rgt);
}
友元布尔运算符>=(常数T&lft、常数T&rgt){
返回!如果左侧>右侧,则运算符0
内部凸轮轴位置(常开和右开)常开{
自动t1=std::tie(a、b、c);
自动t2=std::tie(rhs.a_、rhs.b_、rhs.c_);
自动cmp=t1t2-1:0);
返回cmpMode_*cmp;
}
私人:
INTA_;
int b_;
国际货币基金组织;
};//福
intfoo::cmpMode_u2;=1;
int main(){
Foo f1{1,1,1};
Foo f2{1,1,1};
Foo f3{1,1,2};
Foo f4{1,2,1};
Foo::SetDefaultComparator();
这个把戏可能是相关的。这个把戏可能是相关的。这个问题