Я бы написал функцию так:
int fun(int a, int b, int c, int d) {
if (a) return a;
else if (b) return b;
else if (c) return c;
return d;
}
Она чистая и короткая. Я мог бы остановиться здесь, но давайте посмотрим, что можно сделать ...
Существует алгоритм, который уже почти делает то, что вы хотите. Небольшая модификация решения в этом ответе :
#include <algorithm>
#include <initializer_list>
template <typename T>
T first_non_zero_or_zero(const std::initializer_list<T>& args)
{
auto it = std::find_if_not(args.begin(),args.end(),[](auto v){ return v==0;});
return (it != args.end()) ? *it : 0;
}
Недостаток использования функции для логических выражений не в корне. Если вы вызываете функцию через:
auto x = first_non_zero_or_zero( { foo(), expensive_function() });
, то должен вызываться expensive_function
, независимо от того, что возвращает foo
. Способ восстановить возможность короткого замыкания состоит в том, чтобы вместо этого передать вызываемые объекты, это будет
template <typename F>
auto first_non_zero_or_zero(F f){ return f();}
template <typename First,typename...F>
auto first_non_zero_or_zero(First f,F... others){
if (auto temp = f()) return temp;
return first_non_zero_or_zero(others...);
}
int foo(){ return 0;}
int expensive_function(){ return 42;}
int main()
{
std::cout << first_non_zero_or_zero(foo,expensive_function);
return 0;
}
Однако это сделает вызовы излишне подробными при вызове с простым int
s, так как вам нужно обернуть их в вызываемом:
int fun(int a,int b,int c) {
first_non_zero( [](){ return a;},
[](){ return b;},
[](){ return c;})
}
Заключение: не усложняйте вещи более необходимыми. Функции должны делать одно. Единственное, что делает ваш fun
, - это возвращает первое ненулевое из 4 целых чисел, и if-else
- самый простой способ сделать это.