cfunctionconst-correctnessqualifiers

Is there a way to create qualifier-preserving functions in C?


I have a function that accepts a pointer but does not modify the pointed data, but returns the same pointer or a derivative thereof. I could make the pointer const:

const void *some_read_only_operation(const void *ptr) {
    // Do work with ptr
    return ptr;
}

However, this means if I call the function, I will not be able to manipulate the result without a cast, even if the pointer I passed was not const. On the contrary, if I make the pointers and return type in the function non const then I will need a cast to pass any pointer to the function that is const. And I will get a non const pointer back so I have broken const safety.

Is there any way to create a function in C that repects const correctness (const in means const out and non const in means non const out) without having to write 2 separate functions? If not, how close can I get?

Note: This seems to be the type of question that is likely to have been asked before. I tried to search for duplicates using keywords like const function return or qualifier preserving function but I could not find any.


Solution

  • You can use _Generic for this:

    /**
     * Cast a pointer to `void *` while keeping qualifiers, e.g.
     *
     *     struct foo *   => void *
     *     const char *   => const void *
     *     volatile int * => volatile void *
     */
    #define VOID_CONVERT(ptr) (1 ? (ptr) : (void *)(ptr))
    
    const void *const_fn(const void *ptr) {
        return ptr;
    }
    
    void *non_const_fn(void *ptr) {
        // Re-use the const implementation
        return (void *)const_fn(ptr);
    }
    
    #define fn(ptr) _Generic(VOID_CONVERT(ptr), \
        void *: non_const_fn((void *)(ptr)), \
        const void *: const_fn((const void *)(ptr)))