代码之家  ›  专栏  ›  技术社区  ›  Giogre

为包含许多数值字段的简单“struct”重载比较运算符

  •  0
  • Giogre  · 技术社区  · 4 月前

    假设我有一个普通的旧数据(POD) struct 包含多个数字字段。

    我想重载比较运算符,以便比较POD的两个实例。

    问题是,我需要为那些操作员(比如操作员)设置过载 less() -对于POD中的每个数字字段。

    显然,以下方法不起作用,因为编译器无法区分这两个版本:

    struct my_struct{
        int a;
        int b;
        int c;
    };
    
    bool operator<(const my_struct& one, const my_struct& two) {
        return one.a < two.a;
    }
    
    bool operator<(const my_struct& one, const my_struct& two) {
        return one.b < two.b;
    }
    

    所以我编写了自己的自定义函数 lessThan() ,它接受一个标志并完成这项工作,但我并不特别喜欢这个解决方案(in MWE 下面)因为我不能使用 < 就像我很容易用比较运算符一样。

    #include <iostream>
    #include <iomanip>
    
    struct my_struct{
      int a;
      int b;
      int c;
    };
    
    bool lessThan(const my_struct& one, const my_struct& two, const char flag) {
      switch (flag) {
        case 'a':
          return one.a < two.a;
          break;
        case 'b':
          return one.b < two.b;
          break;        
        case 'c':
          return one.c < two.c;
          break;
        default:
          throw("Either case a, b, or c\n");
          break;
      }     
    }
    
    int main()
    {
      my_struct one{1, 3, 4};
      my_struct two{2, 2, 4};
      std::cout << "one < two: " << std::boolalpha 
                << lessThan(one, two, 'a') << std::endl;
    
      return 0;
    }
    

    是否有方法为自定义POD创建多个比较运算符重载 结构 s有许多数字字段,每个重载都比较其中一个字段?

    (为了给你更多的上下文,我需要这些重载来根据文件的任何特征对文件数组进行排序:例如按维度、按上次修改日期、按包含的文件或子目录的数量等。

    在上述简化示例中,每个POD实例都抽象出一个文件。)


    编辑:

    预期用途示意图:

    sortAccordingToFieldA(std::vector<my_struct>& my_vec, int a){
      for (auto i : my_vec) {
        for (auto j : [std::find(my_vec.begin(), my_vec.end(), i)+1, my_vec.end()] ) {
          if (i < j)  // here '<' is overloaded according to field 'a'
            // sorting operations
        }
      } 
    }
    
    1 回复  |  直到 4 月前
        1
  •  2
  •   Remy Lebeau    4 月前

    在您的“预期用途”示例中, my_vec.begin()+i+1 没有意义,因为 i 是a my_struct 例如,在向量中,它不是向量的索引。A. range-for 循环不使用索引,它使用迭代器。

    无论如何,由于你的函数被命名为 sortAccordingToFieldA() 然后只需访问字段 a 直接,例如:

    void sortAccordingToFieldA(std::vector<my_struct>& my_vec){
        for (auto i = my_vec.begin(); i != my_vec.end(); ++i) {
            for (auto j = i+1; j != my_vec.end(); ++j) {
                if (i->a < j->a) {
                    // sorting operations
                }
            }
        } 
    }
    

    重复以下步骤 sortAccordingToFieldB() sortAccordingToFieldC() 因此,功能。

    如果你真的想要一个更通用的函数,那么你有几个选择:

    • 传递一个指向成员的指针,以便调用者可以指定要比较的字段,例如:

      void sortAccordingToField(std::vector<my_struct>& my_vec, int my_struct::* field){
          for (auto i = my_vec.begin(); i != my_vec.end(); ++i) {
              for (auto j = i+1; j != my_vec.end(); ++j) {
                  if ((*i).*field < (*j).*field) {
                      // sorting operations
                  }
              }
          } 
      }
      
      sortAccordingToField(my_vec, &my_struct::a);
      sortAccordingToField(my_vec, &my_struct::b);
      sortAccordingToField(my_vec, &my_struct::c);
      
    • 传入一个比较函数/lambda,以便调用者可以决定如何比较项目,例如:

      template <typename Comparer>
      void sortAccordingToCompare(std::vector<my_struct>& my_vec, Comparer compare) {
          for (auto i = my_vec.begin(); i != my_vec.end(); ++i) {
              for (auto j = i+1; j != my_vec.end(); ++j) {
                  if (compare(*i, *j)) {
                      // sorting operations
                  }
              }
          } 
      }
      
      sortAccordingToCompare(my_vec, [](auto& i, auto& j){ return i.a < j.a; });
      sortAccordingToCompare(my_vec, [](auto& i, auto& j){ return i.b < j.b; });
      sortAccordingToCompare(my_vec, [](auto& i, auto& j){ return i.c < j.c; });