2

I have two functions that differ only in one parameter (different struct) that nearly do the same processing resulting in a lot of duplication of code. See the following simplified example:

struct foo {
    int a;
};

struct bar {
    int a;
    int b;
};

foo(struct foo *f) {
    do_b();
    // error handling
    f->a = 1;
    do_c();
    // error handling
    do_d();
    // error handling
}

bar(struct bar *b); {
    do_a();
    // error handling
    b->b = 2;
    do_b();
    // error handling
    b->a = 1;
    do_c();
    // error handling
    do_d();
    // error handling
}

Is there some smart way in using only one function eliminating the code duplication?

fliX
  • 773
  • 8
  • 24
  • 5
    Are you willing to change `struct B` to `struct B { struct A a; int b; };`? – Bill Lynch Aug 21 '16 at 18:19
  • 3
    The truly clever ways to do this require that you fully understand the [strict aliasing rule](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). Unfortunately, no one understands that rule ([example](https://stackoverflow.com/questions/39035426/is-aliasing-of-pointers-between-aggregate-c-structs-and-their-members-standards), [example](https://stackoverflow.com/questions/39036857/opaque-structures-with-multiple-definitions),[example](https://stackoverflow.com/questions/38968296/a-type-for-arbitrary-memory-in-c/38969259#38969259)). So you're kind of stuck. – user3386109 Aug 21 '16 at 18:24

1 Answers1

4

Yes there is, but not in a way you imagine. Keeping type safety is really beneficial and it isn't in your best interest to get rid of it (either using pointers to void or struct interitance).

If you have two different types that are defined as separate types for some meaningful reason, then you should have two separate functions that take those types.

What you should do in this case, is to remove the duplication inside those functions:

first( int* a )
{
   do_b();
    // error handling
    *a = 1;
    do_c();
    // error handling
    do_d();
    // error handling
}

foo(struct foo *f) {
    first( &f->a );
}

bar(struct bar *b); {
    do_a();
    // error handling
    b->b = 2;
    first( &b->a );
}
2501
  • 25,460
  • 4
  • 47
  • 87