Reputation: 4388
Is there any better (more readable and / or with less duplicated code) way to write this in C++?
int func()
{
int error = foo(); // can return true/false
if (error != 0) // if an error is returned from foo(), pass it up to the caller of func()
return error;
// otherwise, proceed
error = bar(); // can return true/false
if (error != 0)
return error;
return error; // all calls succeeded, return 0.
}
Upvotes: 1
Views: 1561
Reputation: 40070
If you tend to use this kind of construction often, I'd advise you to define a monad to hide the repetitive behaviour. A simple implementation would go like this.
template<typename Return, Return True>
class Monad
{
Return _result;
public:
Monad() : _result(True) {}
public:
template<typename Function, typename... Args>
Monad&
call(Function f, Args ...args)
{
if (_result == True) {
_result = f(args...);
}
return *this;
}
Return result() { return _result; }
};
bool f() { std::cout << __PRETTY_FUNCTION__ << "\n"; return true; }
bool g(int n) { std::cout << __PRETTY_FUNCTION__ << "\n"; return n == 42; }
bool h() { std::cout << __PRETTY_FUNCTION__ << "\n"; return true; }
int main()
{
Monad<bool, true> m;
const bool result = m.call(f)
.call(g, 56)
.call(h)
.result();
std::cout << std::boolalpha << result << "\n";
}
In this case, only f()
and g(56)
are called (h()
is not); result()
returns false
.
Upvotes: 0
Reputation: 385144
Yes:
void func()
{
foo();
bar();
}
where an exception is thrown up to the caller(s) by either function, if something unexpected occurs.
Error codes are a C-ism.
Upvotes: 1
Reputation: 36597
If you only want an indication of true (non-zero) or false (zero) returned, rather than the actual value returned by your called functions
int func()
{
return foo() || bar();
}
This will return 1
if either foo()
or bar()
return non-zero, with short circuiting so bar()
will not be called if foo()
returns non-zero. In this case, consider returning bool
rather than int
.
If foo()
or bar()
can return a range of non-zero values (e.g. indicating different error conditions) and you need to preserve those
int func()
{
int error = foo();
if (!error) error = bar();
return error;
}
Upvotes: 4
Reputation: 7876
You want outcome<T>
.
https://ned14.github.io/outcome/
But you are going to introduce bigger compile times for the sake of saving a few keystrokes though.
Upvotes: -1
Reputation: 63124
Your version looks nice enough. The only thing I'd avoid is reusing the same variable, but instead use one separate variable per error and scope it tightly:
int func()
{
if (int const error = foo())
return error;
if (int const error = bar())
return error;
return 0;
}
Upvotes: 3