cpointersconstantstypedefhandle

C: void* as handle, loses const expressiveness


I try to consider an API strategy where, in the header file, instead of

typedef struct {...} type_t;
extern void func(const type_t* instance);

I have

typedef void* type_t_handle;
extern void func(const type_t_handle instance);

But I find now that, while before I had options

const type_t* const x; // (1)
const type_t* x;       // (2)
type_t* const x;       // (3)

I now only have option (3) (I checked once I saw that writing const type_t_handle const x; results in a "duplicate ‘const’ declaration specifier" warning). In other words the typedef seems to "bind" the * and the base type and we can't "squeeze" a const in between anymore...

This means that the const in the parameter const type_t_handle instance is useless, I think - it will not result in a "passing argument ... discards ‘const’ qualifier"-type warning which will remind about intention of non-modification...

Is there some solution?


Solution

  • You're correct that the typedef binds the pointer to the base type so you can't make the pointed-to type const.

    You'll need to make a separate typedef for the const qualified version.

    typedef void* type_t_handle;
    typedef const void* const_type_t_handle;
    

    On a side note, rather than using a void * for the type used by the API, instead use an opaque struct i.e. one that is declared in the header file but defined in the implementation file.

    typedef struct xyz type_t;
    extern void func(const type_t* instance);
    

    This give better type safety than using a plain void *.