Remove code redundancy in C through argument type abstraction





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I'm looking for a way to remove code redundancy.



I have two structures A and B having member variables x and y. A third structure C contains two linked lists, one with A* items, the other with B* items. The linked list implementation is not important except for the fact that its nodes store void* data. Therefore accessing the items of this linked list requires knowing if the void* data should be cast to A* or B*.



Here are the structs I'm using:



typedef struct {
int x;
int y;
double z;
} A;

typedef struct {
int x;
int y;
char t;
} B;

typedef struct {
LinkedList* some_as;
LinkedList* some_bs;
} C;


Now, the problem is that I have two very similar functions determining the indexes in the two linked lists in C where new A* and B* items should be inserted, based on the values of x and y. Here is how these functions look like:



int func_for_a(C* c, A* a) 
{
int index = -1;
for (Node* node = c->some_as->head; node; node = node->next) {
++index;
A* current = (A*) node->data;
// some checks on a->x, current->x, a->y, and current->y
// these checks affect `index'
}
return index;
}

int func_for_b(C* c, B* b)
{
int index = -1;
for (Node* node = c->some_bs->head; node; node = node->next) {
++index;
B* current = (B*) node->data;
// same checks on b->x, current->x, b->y, and current->y
// these checks affect `index'
}
return index;
}


What I would like to do is to abstract the type of item (either A* or B*) that needs to be inserted in one of the two linked lists in C, along the lines of:



int func_for_a_or_b(C* c, TYPE type, void* item)
{
Node* head;
if (TYPE == A) {
item = (A*) item;
head = C->some_as->head;
} else {
item = (B*) item;
head = C->some_bs->head;
}

int index = -1;
for (Node* node = head; node; node = node->next) {
++index;
(TYPE)* current = (TYPE*) node->data;
// checks on current->x, item->x, current->y, and item->y
// these checks affect `index'
}
return index;
}


This is not possible because I cannot access members x and y of a void* item. How do I abstract the type of item? Could a macro be used? Is there another solution? Thanks in advance.










share|improve this question


















  • 1





    You can check my answer here: stackoverflow.com/a/32638875/3742943 The question is a bit different, but the answer is completely applicable to your case. The main concept is just create a base struct, and all of your inherited structs must have an instance of it (not a pointer) in their first field.

    – LoPiTaL
    Jan 3 at 12:22











  • Thanks @LoPiTaL, but if I typedef struct { int x; int y; } Coord and exchange the void* item argument of func_for_a_or_b with a Coord coord variable, I am obliged to use a non-anonymous struct in A and B (and I'd really like to avoid doing the whole a->coord.x thing).

    – user3638629
    Jan 3 at 13:16











  • Yes, that is exactly the whole discussion in the comments of the answer. You only have that option or another involving MACROS, also commented in that question, in another answer.

    – LoPiTaL
    Jan 3 at 13:43











  • This is where C++ object hierarchies add power. Much C code is full of these casts from void pointers or from nested objects, and it is all rather hard to maintain.

    – Gem Taylor
    Jan 3 at 13:46






  • 1





    An example of mixing both, the inheritance (in order to mantain the alignment) and the macros (in order to reduce code repetition) could be using anonymous unions: ideone.com/8aiV3G But I am with @GemTaylor, maybe it is time to move to C++...

    – LoPiTaL
    Jan 3 at 13:51


















0















I'm looking for a way to remove code redundancy.



I have two structures A and B having member variables x and y. A third structure C contains two linked lists, one with A* items, the other with B* items. The linked list implementation is not important except for the fact that its nodes store void* data. Therefore accessing the items of this linked list requires knowing if the void* data should be cast to A* or B*.



Here are the structs I'm using:



typedef struct {
int x;
int y;
double z;
} A;

typedef struct {
int x;
int y;
char t;
} B;

typedef struct {
LinkedList* some_as;
LinkedList* some_bs;
} C;


Now, the problem is that I have two very similar functions determining the indexes in the two linked lists in C where new A* and B* items should be inserted, based on the values of x and y. Here is how these functions look like:



int func_for_a(C* c, A* a) 
{
int index = -1;
for (Node* node = c->some_as->head; node; node = node->next) {
++index;
A* current = (A*) node->data;
// some checks on a->x, current->x, a->y, and current->y
// these checks affect `index'
}
return index;
}

int func_for_b(C* c, B* b)
{
int index = -1;
for (Node* node = c->some_bs->head; node; node = node->next) {
++index;
B* current = (B*) node->data;
// same checks on b->x, current->x, b->y, and current->y
// these checks affect `index'
}
return index;
}


What I would like to do is to abstract the type of item (either A* or B*) that needs to be inserted in one of the two linked lists in C, along the lines of:



int func_for_a_or_b(C* c, TYPE type, void* item)
{
Node* head;
if (TYPE == A) {
item = (A*) item;
head = C->some_as->head;
} else {
item = (B*) item;
head = C->some_bs->head;
}

int index = -1;
for (Node* node = head; node; node = node->next) {
++index;
(TYPE)* current = (TYPE*) node->data;
// checks on current->x, item->x, current->y, and item->y
// these checks affect `index'
}
return index;
}


This is not possible because I cannot access members x and y of a void* item. How do I abstract the type of item? Could a macro be used? Is there another solution? Thanks in advance.










share|improve this question


















  • 1





    You can check my answer here: stackoverflow.com/a/32638875/3742943 The question is a bit different, but the answer is completely applicable to your case. The main concept is just create a base struct, and all of your inherited structs must have an instance of it (not a pointer) in their first field.

    – LoPiTaL
    Jan 3 at 12:22











  • Thanks @LoPiTaL, but if I typedef struct { int x; int y; } Coord and exchange the void* item argument of func_for_a_or_b with a Coord coord variable, I am obliged to use a non-anonymous struct in A and B (and I'd really like to avoid doing the whole a->coord.x thing).

    – user3638629
    Jan 3 at 13:16











  • Yes, that is exactly the whole discussion in the comments of the answer. You only have that option or another involving MACROS, also commented in that question, in another answer.

    – LoPiTaL
    Jan 3 at 13:43











  • This is where C++ object hierarchies add power. Much C code is full of these casts from void pointers or from nested objects, and it is all rather hard to maintain.

    – Gem Taylor
    Jan 3 at 13:46






  • 1





    An example of mixing both, the inheritance (in order to mantain the alignment) and the macros (in order to reduce code repetition) could be using anonymous unions: ideone.com/8aiV3G But I am with @GemTaylor, maybe it is time to move to C++...

    – LoPiTaL
    Jan 3 at 13:51














0












0








0








I'm looking for a way to remove code redundancy.



I have two structures A and B having member variables x and y. A third structure C contains two linked lists, one with A* items, the other with B* items. The linked list implementation is not important except for the fact that its nodes store void* data. Therefore accessing the items of this linked list requires knowing if the void* data should be cast to A* or B*.



Here are the structs I'm using:



typedef struct {
int x;
int y;
double z;
} A;

typedef struct {
int x;
int y;
char t;
} B;

typedef struct {
LinkedList* some_as;
LinkedList* some_bs;
} C;


Now, the problem is that I have two very similar functions determining the indexes in the two linked lists in C where new A* and B* items should be inserted, based on the values of x and y. Here is how these functions look like:



int func_for_a(C* c, A* a) 
{
int index = -1;
for (Node* node = c->some_as->head; node; node = node->next) {
++index;
A* current = (A*) node->data;
// some checks on a->x, current->x, a->y, and current->y
// these checks affect `index'
}
return index;
}

int func_for_b(C* c, B* b)
{
int index = -1;
for (Node* node = c->some_bs->head; node; node = node->next) {
++index;
B* current = (B*) node->data;
// same checks on b->x, current->x, b->y, and current->y
// these checks affect `index'
}
return index;
}


What I would like to do is to abstract the type of item (either A* or B*) that needs to be inserted in one of the two linked lists in C, along the lines of:



int func_for_a_or_b(C* c, TYPE type, void* item)
{
Node* head;
if (TYPE == A) {
item = (A*) item;
head = C->some_as->head;
} else {
item = (B*) item;
head = C->some_bs->head;
}

int index = -1;
for (Node* node = head; node; node = node->next) {
++index;
(TYPE)* current = (TYPE*) node->data;
// checks on current->x, item->x, current->y, and item->y
// these checks affect `index'
}
return index;
}


This is not possible because I cannot access members x and y of a void* item. How do I abstract the type of item? Could a macro be used? Is there another solution? Thanks in advance.










share|improve this question














I'm looking for a way to remove code redundancy.



I have two structures A and B having member variables x and y. A third structure C contains two linked lists, one with A* items, the other with B* items. The linked list implementation is not important except for the fact that its nodes store void* data. Therefore accessing the items of this linked list requires knowing if the void* data should be cast to A* or B*.



Here are the structs I'm using:



typedef struct {
int x;
int y;
double z;
} A;

typedef struct {
int x;
int y;
char t;
} B;

typedef struct {
LinkedList* some_as;
LinkedList* some_bs;
} C;


Now, the problem is that I have two very similar functions determining the indexes in the two linked lists in C where new A* and B* items should be inserted, based on the values of x and y. Here is how these functions look like:



int func_for_a(C* c, A* a) 
{
int index = -1;
for (Node* node = c->some_as->head; node; node = node->next) {
++index;
A* current = (A*) node->data;
// some checks on a->x, current->x, a->y, and current->y
// these checks affect `index'
}
return index;
}

int func_for_b(C* c, B* b)
{
int index = -1;
for (Node* node = c->some_bs->head; node; node = node->next) {
++index;
B* current = (B*) node->data;
// same checks on b->x, current->x, b->y, and current->y
// these checks affect `index'
}
return index;
}


What I would like to do is to abstract the type of item (either A* or B*) that needs to be inserted in one of the two linked lists in C, along the lines of:



int func_for_a_or_b(C* c, TYPE type, void* item)
{
Node* head;
if (TYPE == A) {
item = (A*) item;
head = C->some_as->head;
} else {
item = (B*) item;
head = C->some_bs->head;
}

int index = -1;
for (Node* node = head; node; node = node->next) {
++index;
(TYPE)* current = (TYPE*) node->data;
// checks on current->x, item->x, current->y, and item->y
// these checks affect `index'
}
return index;
}


This is not possible because I cannot access members x and y of a void* item. How do I abstract the type of item? Could a macro be used? Is there another solution? Thanks in advance.







c polymorphism void-pointers variable-types






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 3 at 12:16









user3638629user3638629

1106




1106








  • 1





    You can check my answer here: stackoverflow.com/a/32638875/3742943 The question is a bit different, but the answer is completely applicable to your case. The main concept is just create a base struct, and all of your inherited structs must have an instance of it (not a pointer) in their first field.

    – LoPiTaL
    Jan 3 at 12:22











  • Thanks @LoPiTaL, but if I typedef struct { int x; int y; } Coord and exchange the void* item argument of func_for_a_or_b with a Coord coord variable, I am obliged to use a non-anonymous struct in A and B (and I'd really like to avoid doing the whole a->coord.x thing).

    – user3638629
    Jan 3 at 13:16











  • Yes, that is exactly the whole discussion in the comments of the answer. You only have that option or another involving MACROS, also commented in that question, in another answer.

    – LoPiTaL
    Jan 3 at 13:43











  • This is where C++ object hierarchies add power. Much C code is full of these casts from void pointers or from nested objects, and it is all rather hard to maintain.

    – Gem Taylor
    Jan 3 at 13:46






  • 1





    An example of mixing both, the inheritance (in order to mantain the alignment) and the macros (in order to reduce code repetition) could be using anonymous unions: ideone.com/8aiV3G But I am with @GemTaylor, maybe it is time to move to C++...

    – LoPiTaL
    Jan 3 at 13:51














  • 1





    You can check my answer here: stackoverflow.com/a/32638875/3742943 The question is a bit different, but the answer is completely applicable to your case. The main concept is just create a base struct, and all of your inherited structs must have an instance of it (not a pointer) in their first field.

    – LoPiTaL
    Jan 3 at 12:22











  • Thanks @LoPiTaL, but if I typedef struct { int x; int y; } Coord and exchange the void* item argument of func_for_a_or_b with a Coord coord variable, I am obliged to use a non-anonymous struct in A and B (and I'd really like to avoid doing the whole a->coord.x thing).

    – user3638629
    Jan 3 at 13:16











  • Yes, that is exactly the whole discussion in the comments of the answer. You only have that option or another involving MACROS, also commented in that question, in another answer.

    – LoPiTaL
    Jan 3 at 13:43











  • This is where C++ object hierarchies add power. Much C code is full of these casts from void pointers or from nested objects, and it is all rather hard to maintain.

    – Gem Taylor
    Jan 3 at 13:46






  • 1





    An example of mixing both, the inheritance (in order to mantain the alignment) and the macros (in order to reduce code repetition) could be using anonymous unions: ideone.com/8aiV3G But I am with @GemTaylor, maybe it is time to move to C++...

    – LoPiTaL
    Jan 3 at 13:51








1




1





You can check my answer here: stackoverflow.com/a/32638875/3742943 The question is a bit different, but the answer is completely applicable to your case. The main concept is just create a base struct, and all of your inherited structs must have an instance of it (not a pointer) in their first field.

– LoPiTaL
Jan 3 at 12:22





You can check my answer here: stackoverflow.com/a/32638875/3742943 The question is a bit different, but the answer is completely applicable to your case. The main concept is just create a base struct, and all of your inherited structs must have an instance of it (not a pointer) in their first field.

– LoPiTaL
Jan 3 at 12:22













Thanks @LoPiTaL, but if I typedef struct { int x; int y; } Coord and exchange the void* item argument of func_for_a_or_b with a Coord coord variable, I am obliged to use a non-anonymous struct in A and B (and I'd really like to avoid doing the whole a->coord.x thing).

– user3638629
Jan 3 at 13:16





Thanks @LoPiTaL, but if I typedef struct { int x; int y; } Coord and exchange the void* item argument of func_for_a_or_b with a Coord coord variable, I am obliged to use a non-anonymous struct in A and B (and I'd really like to avoid doing the whole a->coord.x thing).

– user3638629
Jan 3 at 13:16













Yes, that is exactly the whole discussion in the comments of the answer. You only have that option or another involving MACROS, also commented in that question, in another answer.

– LoPiTaL
Jan 3 at 13:43





Yes, that is exactly the whole discussion in the comments of the answer. You only have that option or another involving MACROS, also commented in that question, in another answer.

– LoPiTaL
Jan 3 at 13:43













This is where C++ object hierarchies add power. Much C code is full of these casts from void pointers or from nested objects, and it is all rather hard to maintain.

– Gem Taylor
Jan 3 at 13:46





This is where C++ object hierarchies add power. Much C code is full of these casts from void pointers or from nested objects, and it is all rather hard to maintain.

– Gem Taylor
Jan 3 at 13:46




1




1





An example of mixing both, the inheritance (in order to mantain the alignment) and the macros (in order to reduce code repetition) could be using anonymous unions: ideone.com/8aiV3G But I am with @GemTaylor, maybe it is time to move to C++...

– LoPiTaL
Jan 3 at 13:51





An example of mixing both, the inheritance (in order to mantain the alignment) and the macros (in order to reduce code repetition) could be using anonymous unions: ideone.com/8aiV3G But I am with @GemTaylor, maybe it is time to move to C++...

– LoPiTaL
Jan 3 at 13:51












0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54022130%2fremove-code-redundancy-in-c-through-argument-type-abstraction%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54022130%2fremove-code-redundancy-in-c-through-argument-type-abstraction%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

Npm cannot find a required file even through it is in the searched directory