Вчера вечером я написал следующий фрагмент кода для выполнения некоторой арифметической операции (сумма, умножение, вычитание, деление).Обобщение указателей функций
data operation(int oper, data e1, data e2){
data res;
basic b;
//pointer to a funcion that takes two int input and return an int
int (*funIntPtr)(int,int);
float (*funFloatPtr)(float,float);
funIntPtr = NULL;
funFloatPtr= NULL;
//I look for the function to be called
switch (oper) {
case MINUS:
//*functionPtr = &subInt;
switch (e1.b.type) {
case basic_int_value:funIntPtr = subInt;break;
case basic_float_value:funFloatPtr = subFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
case PLUS :
switch (e1.b.type) {
case basic_int_value:funIntPtr = addInt;break;
case basic_float_value:funFloatPtr = addFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
case MULTIPLY:
switch (e1.b.type) {
case basic_int_value:funIntPtr = mulInt;break;
case basic_float_value:funFloatPtr = mulFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
case DIVIDE :
switch (e1.b.type) {
case basic_int_value:funIntPtr = divInt;break;
case basic_float_value:funFloatPtr = divFloat;break;
case basic_boolean_value:
yyerror("boolean arithmetic operation are NOT_ALLOWED");
exit(NOT_ALLOWED);
break;
}
break;
default:
yyerror("what now?");
exit(BUGGY_THE_CLOWN);
break;
}
//look for values to be used
if(funIntPtr == NULL && funFloatPtr == NULL){
yyerror("no function found for the specified operation..");
exit(BUGGY_THE_CLOWN);
}
res.type = basic_dataType;
res.b.type = e1.b.type;//inherithed
switch (e1.b.type) {
case basic_int_value:
{
res.b.i = funIntPtr(e1.b.i, e2.b.i);
}
break;
case basic_float_value:
{
res.b.f = funFloatPtr(e1.b.f, e2.b.f);
}
break;
case basic_boolean_value:
default:
yyerror("no data found for the specified operation..");
exit(BUGGY_THE_CLOWN);
}
return res;
}
В первой части я нахожу функцию, которая будет использоваться, а во второй части я собираю входные данные, которые будут использоваться. Он отлично работает и служит цели.
typedef struct data{
dataType type;
union{
complex c;
basic b;
};
}data;
данные - это структура, которая содержит либо значения базовых типов, либо комплексные значения. Сложными значениями являются типы и структуры массивов. О каком, на данный момент, мне все равно.
typedef struct basic{
basicType type;
union{
int i;
float f;
bool b;
};
}basic;
Базовые значения atm содержат только целые числа, поплавки и булевы.
Но мне было интересно, смогу ли я сделать его более компактным и эффективным. Например, я объявил два указателя на функцию, но я использую только один из них. Есть ли способ обобщить указатель на функцию?
Я знаю, что я должен объявлять типы ввода и тип возвращаемого значения, но в этом случае было бы здорово отложить такую специализацию функций, чтобы иметь только один указатель. Возможно ли это, или я должен изменить способ решения проблемы?
Любое конструктивное предложение хорошо принимается :)
Предоставить [mcve]. Что такое 'данные'? – Olaf
В первой части вы можете выбрать 'struct {int (* funIntPtr) (int, int); float (* funFloatPtr) (float, float); } ', и оставьте проверку типа ко второй части. –
У вас есть проблемы с копированием/вставкой в 'case DIVIDE' (это то же самое, что и' case MULTIPLY'), а также вы должны делить на 0. –