"Chris M. Thomasson" <
chris.m.thomasson.1@gmail.com> writes:
I must have completely missed it. Sorry about that. Please redefine?
It's going to seem silly after all these exchanges. I simply wanted to
know why you chose to use const as you originally posted:
| struct object_prv_vtable {
| int (*fp_destroy) (void* const);
| int (*fp_read) (void* const, void*, size_t);
| int (*fp_write) (void* const, void const*, size_t);
| };
because that looks peculiar (to the point of being arbitrary) to me.
You went on to talk about "self" pointers being const pointers to const
void, but that was not what you wrote, so it did not address what I was
asking about.
In general, const qualified argument types are rarely used and are even
more rarely used in function (or type) declarations because there have
no effect at all in that position. For example, I can assign fp_destroy
from a function declared without the const-qualified parameter:
int destroy(void *self) { /* ... */; return 1; }
...
vtab.fp_destroy = destroy;
or, if I do want the compiler to check that the function does not alter
its parameter, I can add the const in the function definition (were it
can be useful) even if it is missing from the declaration:
struct object_prv_vtable {
int (*fp_destroy) (void*);
/* ... */
};
int destroy(void *const self) { /* ... */; return 1; }
...
vtab.fp_destroy = destroy;
But if you want the const there so that the declaration matches the
function defintion, why not do that for all the parameters? Basically,
I would have expercted either this (just ine const where it matters):
struct object_prv_vtable {
int (*fp_destroy) (void *);
int (*fp_read) (void *, void *, size_t);
int (*fp_write) (void *, void const *, size_t);
};
and the actual functions that get assigned to these pointers might, if
you want that extra check, have all their parametera marked const. Or,
for consistency, you might have written
struct object_prv_vtable {
int (*fp_destroy) (void * const);
int (*fp_read) (void * const, void * const, size_t const);
int (*fp_write) (void * const, void const * const, size_t const);
};
even if none of the actual functions have const parameters.
Finally, if you had intended to write what you later went on to talk
about, you would have written either
struct object_prv_vtable {
int (*fp_destroy) (const void *);
int (*fp_read) (const void *, void *, size_t);
int (*fp_write) (const void *, void const *, size_t);
};
or
struct object_prv_vtable {
int (*fp_destroy) (const void * const);
int (*fp_read) (const void * const, void * const, size_t const);
int (*fp_write) (const void * const, void const * const, size_t const);
};
TL;DR: where you put the consts in the original just seemed arbitrary.
I'll also note that the term "const pointer" is often used when the
pointer is not const! It most often mean that the pointed-to type is
const qualified. As such, it's best to avoid the term altogether.
-- Ben.