È possibile verificare le caratteristiche dei tipi.
Ad esempio, int
può contenere un valore negativo, mentre char*
non può. Quindi, se ((typeof(param))-1) < 0
, param
non è firmato:
if (((typeof(param))-1) < 0) {
do_something_with_int();
} else {
do_something_with_char_p();
}
Il compilatore ottimizza ovviamente questo fuori.
Prova qui: http://ideone.com/et0v1
Questo sarebbe ancora più facile se i tipi hanno diverse dimensioni.Per esempio, se si vuole scrivere una macro generica che può gestire diverse dimensioni dei caratteri:
if (sizeof(param) == sizeof(char)) {
/* ... */
} else if (sizeof(param) == sizeof(char16_t)) {
/* ... */
} else if (sizeof(param) == sizeof(char32_t)) {
/* ... */
} else {
assert("incompatible type" && 0);
}
GCC ha una __builtin_types_compatible_p()
funzione built-in che possono verificare la compatibilità tipi:
if (__builtin_types_compatible_p(typeof(param), int)) {
func_int(param);
} else if (__builtin_types_compatible_p(typeof(param), char*)) {
func_string(param);
}
Provalo qui: http://ideone.com/lEmYE
È possibile inserire questo in una macro per ottenere ciò che si sta tentando di fare:
#define FUNC(param) ({ \
if (__builtin_types_compatible_p(typeof(param), int)) { \
func_int(param); \
} else if (__builtin_types_compatible_p(typeof(param), char*)) { \
func_string(param); \
} \
})
(Lo ({...})
è un GCC's statement expression, consente a un gruppo di istruzioni di essere un valore.
Il builtin __builtin_choose_expr()
può scegliere l'espressione da compilare. Con __builtin_types_compatible_p questo permette di attivare un errore al momento della compilazione se il tipo di parametro non è compatibile con entrambi int
e char*
: (compilando somehting valido in questo caso)
#define FUNC(param) \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \
, func_int(param) \
, __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \
, func_string(param) \
, /* The void expression results in a compile-time error \
when assigning the result to something. */ \
((void)0) \
) \
)
Questo è in realtà un esempio leggermente modificato da __builtin_choose_expr docs.
Anche se fosse possibile, sarebbe fugace. C non è stato progettato per questo. Usa le strutture e i sindacati, puoi persino ottenere la spedizione in tempo reale in questo modo. –