Alejandro Colomar wrote:
> I've had the idea today of an implementation that would be even better
> for users, not requiring the cast at all.
>
> $ cat execve4.c
> #include <stddef.h>
>
> #ifdef __cplusplus
> # define const_cast(T, p) p
> #else
> # define const_cast(T, p) _Generic(p, const T: (T) (p), default: (p))
> #endif
>
> #ifdef __cplusplus // Have n3749
> int execve(const char *path, const char *const a[], const char *const
> e[]);
> #else
> # define execve(p, a, e) execve(p, const_cast(char*const*,a),
> const_cast(char*const*,e))
> int (execve)(const char *path, char *const a[], char *const e[]);
> #endif
Very nice! This can even be done in Gnulib, without waiting for libc changes.
And for older compilers (that don't support _Generic), we can use an explicit
cast:
#ifdef __cplusplus
# define const_cast(T, p) p
#elif (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 9) > 4) \
|| (defined __clang__ && __clang_major__ >= 3) \
|| (defined __SUNPRO_C && __SUNPRO_C >= 0x5150) \
|| (__STDC_VERSION__ >= 201112L && !defined __GNUC__)
# define const_cast(T, p) _Generic(p, const T: (T) (p), default: (p))
#else
# define const_cast(T, p) (T) (p)
#endif
> The only place programmers would notice the different prototype would be
> in function pointers, but that's where Chris's proposal N3674 would kick
> in. It would allow unidirectional implicit conversions of functions
> where one is more restrictive than the other regarding qualifiers.
I see. Yes, then N3674 makes a lot of sense: The language would feel
incomplete if this implicit conversion from 'char **' to 'const char **'
was allowed in argument passing but not in function pointer types.
Bruno