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;
}
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
|
show 2 more comments
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
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 Itypedef struct { int x; int y; } Coord
and exchange thevoid* item
argument offunc_for_a_or_b
with aCoord coord
variable, I am obliged to use a non-anonymous struct inA
andB
(and I'd really like to avoid doing the wholea->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
|
show 2 more comments
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
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
c polymorphism void-pointers variable-types
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 Itypedef struct { int x; int y; } Coord
and exchange thevoid* item
argument offunc_for_a_or_b
with aCoord coord
variable, I am obliged to use a non-anonymous struct inA
andB
(and I'd really like to avoid doing the wholea->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
|
show 2 more comments
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 Itypedef struct { int x; int y; } Coord
and exchange thevoid* item
argument offunc_for_a_or_b
with aCoord coord
variable, I am obliged to use a non-anonymous struct inA
andB
(and I'd really like to avoid doing the wholea->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
|
show 2 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 thevoid* item
argument offunc_for_a_or_b
with aCoord coord
variable, I am obliged to use a non-anonymous struct inA
andB
(and I'd really like to avoid doing the wholea->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