blob: c6f43b3d29c4276ff7e920fe05405ace0229f150 [file] [log] [blame] [view] [edit]
# ErrorBase object
An error object with error information in it.
It supports multiple layers of error messages, custom contents, custom function and printable.
This would be helpful to convert the error into some actions and logging the error message.
## How to add a new error type?
1. The custom error object needs to inherit the `ErrorBaseObj`.
2. It needs to implement the constructor.
3. It needs to implement `ToReadableString` to convert the error object to a readable string.
4. It needs to implement `SelfCopy` to copy itself.
5. Optional: Define `CustomError` to simplify the usage.
6. Optional: Override the `CreateError` helper function to create some special error type, for example: `nullptr`.
7. Optional: Override the `WrapError` helper function to create some special error.
8. Optional: Implement the move operator to add the support of caller info.
```C++
class CustomErrorObj : public ErrorBaseObj {
public:
explicit ErrorObj(const std::string& error_message)
: error_message_(error_message) {}
explicit ErrorObj(std::string&& error_message)
: error_message_(std::move(error_message)) {}
virtual ~ErrorObj() = default;
hwsec_foundation::error::ErrorBase SelfCopy() const {
return std::make_unique<ErrorObj>(error_message_);
}
std::string ToReadableString() const { return error_message_; }
protected:
ErrorObj(ErrorObj&&) = default;
private:
const std::string error_message_;
};
using CustomError = std::unique_ptr<CustomErrorObj>;
template <typename ErrorType,
typename T,
typename std::enable_if<
std::is_same<ErrorType, CustomError>::value>::type* =
nullptr,
decltype(CustomErrorObj(
std::forward<T>(std::declval<T&&>())))* = nullptr>
CustomError CreateError(T&& error_msg) {
if (error_msg == "") {
return nullptr;
}
return std::make_unique<CustomError>(std::forward<T>(error_msg));
}
```
# Recommended coding style
1. When should we use `auto`? Similar to [the style of unique_ptr](https://google.github.io/styleguide/cppguide.html#Type_deduction).
1. Use `auto` when the error is created by `CreateError<>` or `WrapError<>`
```C++
if (auto err = CreateError<TPM1Error>(0x99)) {
/* Do some error handlings... */
}
```
2. Specify the error type in other cases.
```C++
if (TPM1Error err = SomeMagicFunction()) {
/* Do some error handlings... */
}
```
2. Use Error in the `if` expression:
1. It's fine to do implicit bool conversions when the error is declared inside the if expression.
```C++
if (TPM1Error err = SomeMagicFunction()) {
/* Do some error handlings... */
}
```
2. But we should prevent doing implicit bool conversions when the error isn’t declared in the if expression.
```C++
if (SomeMagicFunction()) {
/* Don’t do this. */
}
```
Please use:
```C++
if (SomeMagicFunction() != nullptr) {
/* This it better */
/* But should think about why we need to drop the extra error information in this case. */
/* For example: Should we log more messages in this case? */
}
```