Попытка перегрузить функцию в языке программирования C с помощью _Generic. Нашли примеры:

Это пример:

#include <stdio.h>
#include <math.h>

void display_float(float dispid) ;
void display_int(int dispid) ;
void display_void(void) ;

#define display(x) _Generic((x), \
          float: display_float, \
          int: display_int,  \
          default: display_float  \
)(x)

void display_void(void){
    printf("display id: 0\n") ;
}

void display_float(float dispid){
   printf("display id: %f\n", dispid) ;
}

void display_int(int dispid){
    printf("display id: %d\n", dispid) ;
}

void main(void){

    display(5) ;
    display(6.5) ;
}

Теперь я также хочу перегрузить функцию с помощью display(). Это означает, что функция получит void, вызовет функцию display_void() и отобразит 0. Похоже, что это не так. Любая помощь будет оценена.

РЕДАКТИРОВАТЬ 1:

Также см. Примеры здесь. Один из примеров (я думаю) передает указатель на пустоту. Можно ли это реализовать?

c
1
ASarkar 28 Май 2019 в 06:32

2 ответа

Лучший ответ

Конечно. Макрос перегрузки по числу аргументов.

void display_float(float dispid) ;
void display_int(int dispid) ;
void display_void(void) ;

#define _display_1(x) _Generic((x), \
          float: display_float, \
          int: display_int,  \
          default: display_float  \
)(x)
#define _display_0()  display_void()
#define _display_N(_0,_1,N,...)  _display_ ## N
#define display(...) _display_N(_0,##__VA_ARGS__,1,0)(__VA_ARGS__)

int main() {
    display();
    display(1);
    display(1.1);
}

Протестировано на богоболте.

Обратите внимание, что , ##__VA_ARGS__ является расширением gcc, которое не описано в стандарт С

5
KamilCuk 28 Май 2019 в 05:55

Попытка перегрузки функции в языке программирования C

C11 не имеет перегрузка функций и _Generic для универсальность , not для перегрузки, проверьте это, прочитав n1570. Подумайте о переходе на C ++ (или еще лучше, Rust), который обеспечивает перегрузку функций. Обратите внимание, что нельзя иметь аргумент void (не void*, просто void)) для функции C, поэтому " top "супертип в C, который будет супертипом других типов (и это из-за соглашения о вызовах и соображения ABI, делающие C низкоуровневым языком программирования, иногда даже называемым" портативный ассемблер "). Узнайте больше о абстрактной интерпретации и системы типов, пожалуйста.

Если бы _Generic был перегружен, члены комитета по стандартизации C11 - все эксперты по языку программирования и достаточно хорошие английские писатели - назвали бы его как _Overload, но они этого не сделали.

Пища для размышлений (при условии, что stderr и stdin работают так, как вы хотите, чтобы они работали) :
как насчет некоторых гипотетический display(stderr) или display(*stdin) или display("abc")?

(неправильное предложение ниже, а затем совет)

Плохой подход

( это не работает! )

Ваш display_void должен принять некоторые аргументы, например,

void display_void(void*p) { printf("p@%p\n", p);

Тогда вы можете иметь:

#define display_anything(P) display_void((void*)(&(P)))

С участием

#define display(x) _Generic((x), \
      float: display_float, \
      int: display_int,  \
      default: display_anything  \
)(x)

Лучший совет

Поскольку это не работает (и не работает), создайте свой код другим способом . Например, рассмотрите возможность использования тегового объединения, например . Изучите реализацию GVariant (из Glib) для получения вдохновения.

1
Basile Starynkevitch 28 Май 2019 в 06:11