Попытка перегрузить функцию на языке программирования 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:
Также см. примеры здесь. Один из примеров (я думаю) — это передача указателя на пустоту. Можно ли это реализовать?
@JonathanLeffler: я подозревал это. Но также см. мой РЕДАКТИРОВАТЬ 1 в вопросе.
Передавать указатель на void легко — да, с этим можно справиться. Он не передает ничего сложного (я думаю, что это невозможно сделать, даже если C11 разрешает макросам пустые аргументы).
Я откатил вашу правку. Пожалуйста, не включайте ответы в свой вопрос. Это обесценивает их и довольно грубо по отношению к людям, которые жертвуют своим временем, чтобы ответить. Если у вас есть новый вопрос о другом обновленном коде, опубликуйте его как новый вопрос.
Без лучших примеров (или какого-то подлинного минимальный воспроизводимый пример в самом вашем вопросе) вопрос неясен, и я проголосовал за его закрытие.
void main(void) должно быть int main(void).
Вы можете определить макрос display0, который не принимает аргументов, и макрос display1, принимающий один аргумент. Когда вы пишете вызов, вы знаете, сколько аргументов вы передаете, поэтому выбор макроса для вызова не является большой проблемой.
@BasileStarynkevitch: воспроизводимый пример приведен в самом вопросе. Не уверен, что еще вы просите. Все остальные, кажется, прекрасно понимают, в чем вопрос.
Поскольку я ответил речь идет не о перегрузке функций, то, по крайней мере, заголовок вопроса неверен, и, по крайней мере, это следует исправить; а _Generic должен даже намекать не на перегрузку, а на универсальность
Оригинальное название было отредактировано кем-то другим. Кроме того, ссылка, которую я дал в самом начале, показывает, что перегрузку функций в C можно выполнить с помощью _Generic.
Я утверждаю, что речь идет об общих функциях, а не о перегрузке функций. Смотрите пищу для размышлений в моем ответе. Но я не являюсь носителем английского языка (и во Франции меня учили, даже в средней школе, тщательно подбирать слова)





Trying to overloading a function in C programming language
С11 не содержит перегрузка функций и _Generic для универсальность, нет для перегрузки, проверьте это, прочитав n1570. Рассмотрите возможность перехода на C++ (или, что еще лучше, на Ржавчина), который обеспечивает перегрузку функций. Обратите внимание, что использование аргумента void (не void*, просто void) для функции C является незаконным, поэтому в C нет супертипа "верх", который был бы супертипом других типов (и это из-за соглашения о вызовах и АБИ соображений, делающих C языком программирования низкий уровень, иногда даже называемым «ассемблером портативный»). Узнайте больше о абстрактная интерпретация и системы типов, пожалуйста.
Если бы _Generic означало перегрузку, члены комитета по стандарту C11 — все эксперты по языкам программирования и достаточно хорошие англоязычные писатели — назвали бы его как _Overload, но они поступили так мудро.
Пища для размышлений (при условии, что и stderr, и stdin работают так, как вы хотите, чтобы они работали) :
а как насчет некоторых гипотетических display(stderr) или display(*stdin) или display("abc") ?
(a wrong suggestion below, followed by a better advice)
(это не работает!)
Ваш 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)
Так как это не работает (и не работает), спроектируйте свой код каким-то другим способом. Например, рассмотрите возможность наличия некоторого помеченный союз, например здесь. Посмотрите на реализацию GВариант (от Glib) для вдохновения.
Пожалуйста, посмотрите мой РЕДАКТИРОВАТЬ 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, не описанный в стандарте C.
Не будет хорошо работать с display(stderr); или FILE* f = fopen(__FILE__, "r"); display(f); или в Linux с использованием стат(2) с struct stat st; stat("/dev/zero", &st);, за которым следует display(st); или display(&st); пожалуйста, улучшите свой ответ для display(stderr)
@BasileStarynkevitch Я не понимаю твоей точки зрения. Нет ни display(FILE*), ни display(struct stat*), ни display(struct stat) перегрузок, поэтому они не должны работать. Я не понимаю вашей точки зрения. Если вы добавите их, они будут работать. Почему display(stderr) должно работать? ОП этого не просил. Я не буду.
ОП мечтает о вещи общийdisplay, и я пытаюсь объяснить (извините, я не носитель английского языка), что такая вещь не может существовать (если только ОП не определит display_FILEявно и display_stat, чего он не хочет!)
@BasileStarynkevitch ? Now I also want to overload the function with display(). Meaning the function would intake a void, call the function display_void() - это очень конкретно. Мы хотим написать display() и заставить его звонить display_void(). Ни больше ни меньше. Я не знаю ОП настолько хорошо, чтобы угадывать, о чем она / он мечтает и делает или не хочет. В посте ОП около 6 правок, возможно, ваш браузер мог его испортить.
@ Камил Кук: тогда сделайте то, что я сделал: проголосуйте, чтобы закрыть вопрос как неясный.
Вы не можете перегрузить отсутствие параметра. Ваш выбор
display_floatпо умолчанию в_Genericудивителен, но изменение его наdisplay_voidмало поможет; вам нужно будет предоставить аргумент макросуdisplay, и он будет передан любой функции в предложенииdefault, и если бы это былdisplay_void, он не ожидал бы никаких аргументов. Однако_Genericожидает выражение-присваивания в качестве первого аргумента, и ни пустая последовательность токенов, ни()не приемлемы в качестве выражение-присваивания, поэтому вы не можете использовать_Genericдля перегрузки().