Сабж. Как можно сделать подобное в этом коде? Если бы не поле operand, то делается всё просто.
struct foo {
int foo_a;
int foo_b;
int foo_c;
};
struct barstruct {
int c;
int d;
foo * get_foo(int n) { return &f; }
private:
foo f;
};
#define FUNC(res, operand) \
else if (fillbuff(buf) == res) \
{ \
foo * f = bar.get_foo( bar.c ); \
if (f) \
return f->operand; \
}
int fillbuff(char const * buf)
{
int i;
/// ...
return i;
}
int main()
{
//...
barstruct bar;
char * buf;
if (fillbuff(buf) == 0) {
return 0;
}
FUNC(1, foo_a)
FUNC(2, foo_b)
FUNC(3, foo_c)
//...
}
Здравствуйте, Аноним, Вы писали:
А>Сабж. Как можно сделать подобное в этом коде? Если бы не поле operand, то делается всё просто.
int func(int res, foo::*int operand)
{
...
return f->*operand;
}
...
int func(1, &foo::foo_a);
Здравствуйте, Аноним, Вы писали:
А>Сабж. Как можно сделать подобное в этом коде? Если бы не поле operand, то делается всё просто.
А>...
Давненько я такого кошмара не видел, это во истину шедевр
А переделать макрос FUNC в функцию без изменения окружающего кода невозможно по той простой причине, этот макрос ветвит вызывающий код на целых три(!) ветки.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Аноним, Вы писали:
А>>Сабж. Как можно сделать подобное в этом коде? Если бы не поле operand, то делается всё просто.
А>>...
R>Давненько я такого кошмара не видел, это во истину шедевр А переделать макрос FUNC в функцию без изменения окружающего кода невозможно по той простой причине, этот макрос ветвит вызывающий код на целых три(!) ветки.
Чтобы не выглядеть неконструктивным критиканом, предложу вариант рефакторинга. Хотя, сразу должен сказать, что у меня возникли сомнения в том, что автор этого кода понимал ЧТО он делает. Особенно странным выглядит множественный вызов функции
fillbuff в то время, когда выполняется анализ результата этой же функции.
Тем, не менее, не смотря на кажущуюся (мне, по крайней мере) бессмысленность этого кода, предложенный ниже вариант по своему эффекту полностью идентичен исходному.
int main()
{
struct
{
int result_code;
int foo::*field;
} cases[] = {
{1, &foo::foo_a},
{2, &foo::foo_b},
{3, &foo::foo_c},
};
const int cases_count = sizeof(cases) / sizeof(*cases);
barstruct bar;
char * buf;
if (fillbuff(buf) == 0)
return 0;
for (int i = 0; i < cases_count; ++i)
if (fillbuff(buf) == cases[i].result_code)
{
foo * f = bar.get_foo( bar.c );
if(!f)
break;
return f->*cases[i].field;
}
}
R>Тем, не менее, не смотря на кажущуюся (мне, по крайней мере) бессмысленность этого кода, предложенный ниже вариант по своему эффекту полностью идентичен исходному.
R>R>int main()
R>{
R> struct
R> {
R> int result_code;
R> int foo::*field;
R> } cases[] = {
R> {1, &foo::foo_a},
R> {2, &foo::foo_b},
R> {3, &foo::foo_c},
R> };
R> const int cases_count = sizeof(cases) / sizeof(*cases);
R> barstruct bar;
R> char * buf;
R> if (fillbuff(buf) == 0)
R> return 0;
R> for (int i = 0; i < cases_count; ++i)
R> if (fillbuff(buf) == cases[i].result_code)
R> {
R> foo * f = bar.get_foo( bar.c );
R> if(!f)
R> break;
R> return f->*cases[i].field;
R> }
R>}
R>
Привиденный пример синтетический, просто для того чтобы показать от чего хочется избавится. Здесь интересует прежде всего не оптимизация, а какими путями можно избавится от макроса. Учитывая что во время работы fillbuff динамически создаются различные структуры в barstruct и их количество не известно при компиляции.