开发者

Comparing arrays of objects with arrays of fields of objects

开发者 https://www.devze.com 2023-02-17 12:39 出处:网络
Is there a good way to compare arr[i].A to A[i] and arr[i].B to B? int A[10], B[10]; class Foo { int A, B;

Is there a good way to compare arr[i].A to A[i] and arr[i].B to B?

int A[10], B[10];

class Foo {
   int A, B;
};

Foo arr[10];

I could do the following:

for (i=0;i<10;i++) {
   if (A[i] == arr[i].A) {}
   if (B[i] == arr[i].B) {}
}

But, this is painful especially if there are a lot of fields, and the if() conditional does the same thing over and over, there will be a lot of code duplication. What I really want to do is parametrize this somehow and call a function like (test(A,arr)). I guess I can solve this by u开发者_开发问答sing #define macros, but that seems ugly.

Any suggestions?

Also I want to avoid creating a new array of Foo objects because I don't want to create new objects that may have many fields I don't care about, also I may want to compare different subsets of fields.


IF the ranges are of equal size you can use std::equal with a predicate (or a lambda):

bool CompA( int lhs, Foo rhs ){
   return lhs == rhs.A;
};
...
// to check for equality
bool result = std::equal( A, A + 10, arr, CompA );
...
// to see where the mismatch is
std::pair< int*, Foo* > result = std::mismatch( A, A + 10, arr, CompA );
size_t index = result.first - A;
if( index < 10 ){
   std::cout << "Mismatch at index " << index << " A = " << *result.first << " Foo.A = " << (*result.second).A << std::endl;
}


There are standard-library algorithms for doing operations on containers (including arrays, kinda) but using them typically produces code that's harder to read and maintain, and no shorter or more efficient, than straightforward loops.

However, it sounds as if you might want to know about pointers-to-members.

bool all_equal(int Foo::* member, const Foo * obj_array, const int * elem_array, size_t n) {
  for (int i=0; i<n; ++i) {
    if (obj_array[i].*member != elem_array[i]) return false;
  }
  return true;
}

...

if (all_equal(&Foo::A, arr, A, 10) && all_equal(&Foo::*B, arr, B, 10)) ...

although actually you should probably generalize it:

template<typename T, typename E>
bool all_equal(E T::* member, const T* obj_array, const E* elem_array, size_t n) {
  for (int i=0; i<n; ++i) {
    if (obj_array[i].*member != elem_array[i]) return false;
  }
  return true;
}

(Danger: all code above is untested and may consist entirely of bugs.)

0

精彩评论

暂无评论...
验证码 换一张
取 消