C++ 用正确的方法或设计模式来简化类中的'operatorX'函数,以便按给定顺序比较相同类型的属性?
过去,我通过编写一个以比较函数为参数的helper函数,减少了数据类型类的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) {
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();
这个把戏可能是相关的。这个把戏可能是相关的。这个问题