Перегрузка функций внутри структуры C99 - PullRequest
0 голосов
/ 07 июля 2019

Обычно в C99 вы можете добиться перегрузки функций (количество аргументов, а не перегрузка типов) с помощью VA_ARGS и некоторого макроса, например:

#define THIRD_PARAMETER(_1,_2,_3,...) _3
#define NOTHING

например:

void pr1(int x);
void pr2(int x, int y);
#define pr(...) THIRD_PARAMETER(__VA_ARGS__, pr2, pr1, NOTHING)(__VA_ARGS__)

(я добавляю макрос NOTHING, чтобы C99 не жаловался на нулевой аргумент, передаваемый ..., когда я вызываю pr(100) для печати 100, я хочу, чтобы моя программа была полностью совместима с C99)

Но проблема в том, что pr не является функцией, поэтому его нельзя назначить указателю на функцию внутри структуры:

 // this is a dynamic array
 struct array {
     // ...
     void (*insert)(struct array * a, ...);
     // ...
 };

Предположим, у меня есть 3 версии вставки: single_insert, множественный_интервал, range_insert, которые имеют 3,4,5 аргумента соответственно. Как я могу реализовать перегрузку функции (количество аргументов) внутри структуры C99? это возможно?

Ответы [ 2 ]

2 голосов
/ 07 июля 2019

Предположим, у меня есть 3 версии вставки: single_insert, множественный_insert, range_insert, которые имеют 3,4,5 аргументов соответственно.Как я могу реализовать перегрузку функций (количество аргументов) внутри структуры C99?возможно ли это?

Вы можете объявить указатель функции, который не предоставляет прототип, который, следовательно, будет совместим с функциями с разными номерами и даже разными типами аргументов:

void (*insert)();

Но какая бы функция ни указала на ту, которая будет вызываться через такой указатель - вы не получите выбор различных функций на основе списка аргументов.Кроме того, на аргументы будут распространяться аргументы по умолчанию, а продвигаемые аргументы должны совпадать по типу и номеру с фактическими параметрами функции.

Если объявление указателя предоставляет прототип и вы вызываетечтобы функционировать через него, эта функция должна иметь совместимую подпись, поскольку «совместимость» определена в спецификациях языка.В частности, объявления функций с переменными и не переменными несовместимы друг с другом, поэтому ваша идея объявить указатель с помощью прототипа с переменными параметрами не соответствует.

Таким образом, на самом деле это не имеет ничего общего сструктур.Скорее проблема заключается в указателях функций.Вы можете применить макрос трюк, такой как вы описали, чтобы выбрать из нескольких указателей на функции, или вы можете написать функцию переменной оболочки, которая выполняет такой выбор, но вы не можете закодировать такой выбор в самом указателе.

0 голосов
/ 07 июля 2019

Вы можете присвоить указателю на функцию .insert произвольный тип (если вы используете что-то вроде void (*)(), то функции, возвращающие пустые значения, которые принимают аргументы, которые не являются короткими или переменными, будут неявно преобразовываться в этот тип указателя, но этоне является обязательным), а затем есть макрос INSERT(&myarray, ...), который будет считать аргументы, приведёт .insert к соответствующему типу согласно количеству и затем вызовет его.

...