Introduce generic 'Result' class
Useful to encapsulate the function result object (in case of having it) or, in case of failure, the failure reason.
This let us clean lot of boilerplate code, as now instead of returning a boolean and having to add a ref arg for the
return object and another ref for the error string. We can simply return a 'BResult<Obj>'.
Example of what we currently have:
```
bool doSomething(arg1, arg2, arg3, arg4, &result, &error_string) {
do something...
if (error) {
error_string = "something bad happened";
return false;
}
result = goodResult;
return true;
}
```
Example of what we will get with this commit:
```
BResult<Obj> doSomething(arg1, arg2, arg3, arg4) {
do something...
if (error) return {"something happened"};
// good
return {goodResult};
}
```
This allows a similar boilerplate cleanup on the function callers side as well. They don't have to add the extra
pre-function-call error string and result object declarations to pass the references to the function.
2022-04-08 16:24:46 -03:00
|
|
|
// Copyright (c) 2022 The Bitcoin Core developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or https://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#ifndef BITCOIN_UTIL_RESULT_H
|
|
|
|
#define BITCOIN_UTIL_RESULT_H
|
|
|
|
|
|
|
|
#include <util/translation.h>
|
2022-07-12 19:28:03 +02:00
|
|
|
|
Introduce generic 'Result' class
Useful to encapsulate the function result object (in case of having it) or, in case of failure, the failure reason.
This let us clean lot of boilerplate code, as now instead of returning a boolean and having to add a ref arg for the
return object and another ref for the error string. We can simply return a 'BResult<Obj>'.
Example of what we currently have:
```
bool doSomething(arg1, arg2, arg3, arg4, &result, &error_string) {
do something...
if (error) {
error_string = "something bad happened";
return false;
}
result = goodResult;
return true;
}
```
Example of what we will get with this commit:
```
BResult<Obj> doSomething(arg1, arg2, arg3, arg4) {
do something...
if (error) return {"something happened"};
// good
return {goodResult};
}
```
This allows a similar boilerplate cleanup on the function callers side as well. They don't have to add the extra
pre-function-call error string and result object declarations to pass the references to the function.
2022-04-08 16:24:46 -03:00
|
|
|
#include <variant>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 'BResult' is a generic class useful for wrapping a return object
|
|
|
|
* (in case of success) or propagating the error cause.
|
|
|
|
*/
|
|
|
|
template<class T>
|
|
|
|
class BResult {
|
|
|
|
private:
|
|
|
|
std::variant<bilingual_str, T> m_variant;
|
|
|
|
|
|
|
|
public:
|
2022-07-12 19:28:03 +02:00
|
|
|
BResult() : m_variant{Untranslated("")} {}
|
|
|
|
BResult(T obj) : m_variant{std::move(obj)} {}
|
|
|
|
BResult(bilingual_str error) : m_variant{std::move(error)} {}
|
Introduce generic 'Result' class
Useful to encapsulate the function result object (in case of having it) or, in case of failure, the failure reason.
This let us clean lot of boilerplate code, as now instead of returning a boolean and having to add a ref arg for the
return object and another ref for the error string. We can simply return a 'BResult<Obj>'.
Example of what we currently have:
```
bool doSomething(arg1, arg2, arg3, arg4, &result, &error_string) {
do something...
if (error) {
error_string = "something bad happened";
return false;
}
result = goodResult;
return true;
}
```
Example of what we will get with this commit:
```
BResult<Obj> doSomething(arg1, arg2, arg3, arg4) {
do something...
if (error) return {"something happened"};
// good
return {goodResult};
}
```
This allows a similar boilerplate cleanup on the function callers side as well. They don't have to add the extra
pre-function-call error string and result object declarations to pass the references to the function.
2022-04-08 16:24:46 -03:00
|
|
|
|
|
|
|
/* Whether the function succeeded or not */
|
|
|
|
bool HasRes() const { return std::holds_alternative<T>(m_variant); }
|
|
|
|
|
|
|
|
/* In case of success, the result object */
|
|
|
|
const T& GetObj() const {
|
|
|
|
assert(HasRes());
|
|
|
|
return std::get<T>(m_variant);
|
|
|
|
}
|
2022-07-12 19:28:03 +02:00
|
|
|
T ReleaseObj()
|
|
|
|
{
|
|
|
|
assert(HasRes());
|
|
|
|
return std::move(std::get<T>(m_variant));
|
|
|
|
}
|
Introduce generic 'Result' class
Useful to encapsulate the function result object (in case of having it) or, in case of failure, the failure reason.
This let us clean lot of boilerplate code, as now instead of returning a boolean and having to add a ref arg for the
return object and another ref for the error string. We can simply return a 'BResult<Obj>'.
Example of what we currently have:
```
bool doSomething(arg1, arg2, arg3, arg4, &result, &error_string) {
do something...
if (error) {
error_string = "something bad happened";
return false;
}
result = goodResult;
return true;
}
```
Example of what we will get with this commit:
```
BResult<Obj> doSomething(arg1, arg2, arg3, arg4) {
do something...
if (error) return {"something happened"};
// good
return {goodResult};
}
```
This allows a similar boilerplate cleanup on the function callers side as well. They don't have to add the extra
pre-function-call error string and result object declarations to pass the references to the function.
2022-04-08 16:24:46 -03:00
|
|
|
|
|
|
|
/* In case of failure, the error cause */
|
|
|
|
const bilingual_str& GetError() const {
|
|
|
|
assert(!HasRes());
|
|
|
|
return std::get<bilingual_str>(m_variant);
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit operator bool() const { return HasRes(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // BITCOIN_UTIL_RESULT_H
|