С++ Универсальный способ вызвать любую функцию дважды
Проблема состоит в следующем: мне необходимо вызвать функцию саму себя ещё раз в случае, если она вернёт false.
Казалось бы, всё очень просто. Но таких функций очень много, и аргументы они принимают разные.
В примере кода сравнивается какой-то конечный результат и в случае необходимости эта функция вызывается ещё один раз.
Проблема в том, что в каждой функции писать это сравнение сложно, долго и опасно.
Можно ли упростить эту задачу с помощью какого-нибудь
defineили универсальной функции, которая бы вызывала переданную функцию не больше двух раз?
Define, например, бы вставлял название функции и её аргументы (как я себе представляю)
bool doSmth(int val)
{
if (res == false) {
static thread_local bool called = false;
if (called) {
called = false;
}
else {
called = true;
return doSmth(val);
}
}
return res;
}
Было бы хорошо, если блок if заменить на какой-нибудь макрос или функцию, например:
bool doSmth(int val)
{
bool res = compute(val);
return CALL_FUNC_AGAIN_IF_FALSE(res);
}
В этом случае функция выполняется ещё один раз, затем возвращается результат независимо от того, true или false.
Ответы (2 шт):
return called || doSmth(val); или о чем?
bool doSmth(int val, bool retry = true)
{
return compute(val) || retry && doSmth(val, false);
}
? Ну или что-нибудь вроде
template<class F, class... Args> auto at_most_twice(F &&f, Args &&...args) {
return std::invoke(f, args...) || std::invoke(f, std::forward<Args>(args)...);
}
Class instance;
at_most_twice(&Class::method, instance, arg1, arg2);
Возможно, более простым решением будет переложить эту задачу на вызывающий код.
bool ff(const char *t) {
puts(t);
return t[0] == '2';
}
bool fff(const char *t, const char *s) {
puts(t); puts(s);
return t[0] == '2';
}
#define call2(f, ...) (f(__VA_ARGS__) || f(__VA_ARGS__))
int main()
{
call2(ff, "123");
call2(fff, "abc", "xxx");
call2(fff, "22", "333");
}
Подробнее о макросах с переменым числом аргументов можно прочесть тут.
Вызываем
avp@avp-desktop:~/avp/hashcode$ g++ t.cpp -O3
avp@avp-desktop:~/avp/hashcode$ ./a.out
123
123
abc
xxx
abc
xxx
22
333
avp@avp-desktop:~/avp/hashcode$
Это?