Перегрузка функции с помощью void - PullRequest
1 голос
/ 28 мая 2019

Попытка перегрузить функцию на языке программирования 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:

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

Ответы [ 2 ]

5 голосов
/ 28 мая 2019

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

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 , не описанное в стандарте C.

1 голос
/ 28 мая 2019

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

C11 не имеет никакой перегрузки функции и _Generic для универсальность , не для перегрузки, проверьте это, прочитав n1570 . Рассмотрите возможность перехода на C ++ (или, что еще лучше, Rust ), который обеспечивает перегрузку функций. Обратите внимание, что нельзя иметь аргумент void (не void*, просто void) для функции C, поэтому в C не существует супертипа "top" , который бы быть супертипом других типов (и это из-за соглашений о вызовах и 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) для вдохновения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...