K
kid joe
Hi all,
Imagine youre making an object-oriented style library, say it deals with
"struct myobj"'s. There is a function
int myobj_init(struct myobj *o, ***);
where what comes in the *** part is what I want to discuss.
Obviously the init function will initialize the fields in the o
structure, maybe allocate some memory or associate other resources. The
*** should be options that can be used to initialize some of the fields.
It seems that the most common way of doing this is to replace *** by
a single parameter like a "struct myobj_options *", where this struct is
something like
struct myobj_options {
size_t initial_size;
int verbose;
int debugging;
etc.
}
Passing a NULL options pointer uses default settings for the options.
If later on the library develops and extra options become available, as
long as the code calling the library creates the struct myobj_options with
calloc and sets some fields, all the extra fields that didnt exist when
the calling code was written, will just be zero. Code using the library
needs to be recompiled but not otherwise rewritten.
What I was thinking was an alternative to this setup, where *** is
replaced by a varargs list:
int myobj_init(struct myobj *o, int n, ...);
Here n is the number of options that are supplied in the varargs. Of
course, the options would have to come in a specified order.
This seems like a nice arrangement to me. Here are some idioms:
myobj_init(&o, 0); /* use defaults for all arguments */
myobj_init(&o, 2, 1000, 1); /* specify first two options and use
defaults for the others */
When new options are added, existing code linking against the library
doesn't even need to be recompiled, unlike in the "options struct" case.
But I don't think I've ever seen this approach used. Is there a reason why
this would be a bad idea?
Cheers,
Joe
Imagine youre making an object-oriented style library, say it deals with
"struct myobj"'s. There is a function
int myobj_init(struct myobj *o, ***);
where what comes in the *** part is what I want to discuss.
Obviously the init function will initialize the fields in the o
structure, maybe allocate some memory or associate other resources. The
*** should be options that can be used to initialize some of the fields.
It seems that the most common way of doing this is to replace *** by
a single parameter like a "struct myobj_options *", where this struct is
something like
struct myobj_options {
size_t initial_size;
int verbose;
int debugging;
etc.
}
Passing a NULL options pointer uses default settings for the options.
If later on the library develops and extra options become available, as
long as the code calling the library creates the struct myobj_options with
calloc and sets some fields, all the extra fields that didnt exist when
the calling code was written, will just be zero. Code using the library
needs to be recompiled but not otherwise rewritten.
What I was thinking was an alternative to this setup, where *** is
replaced by a varargs list:
int myobj_init(struct myobj *o, int n, ...);
Here n is the number of options that are supplied in the varargs. Of
course, the options would have to come in a specified order.
This seems like a nice arrangement to me. Here are some idioms:
myobj_init(&o, 0); /* use defaults for all arguments */
myobj_init(&o, 2, 1000, 1); /* specify first two options and use
defaults for the others */
When new options are added, existing code linking against the library
doesn't even need to be recompiled, unlike in the "options struct" case.
But I don't think I've ever seen this approach used. Is there a reason why
this would be a bad idea?
Cheers,
Joe