DEV Community

Discussion on: How I am handling errors in a freestanding environment

Collapse
 
pgradot profile image
Pierre Gradot • Edited

Hi!

You can add 'cpp' after the triple back-ticks in order to color your code ;)

Since you decide not to support old stuff, why didn't you choose to use std::variant from C++17?

A quickly written code gave me this (its's not as complete as yours, of course):

#include <optional>
#include <variant>
#include <iostream>

template<typename ValueType, typename ErrorType>
class ValueOrError {
    static_assert(not std::is_same_v<ValueType, ErrorType>, "No supported");

public:
    explicit ValueOrError(ValueType value) : valueOrError_m{std::move(value)} {}

    explicit ValueOrError(ErrorType error) : valueOrError_m{std::move(error)} {}

    [[nodiscard]] bool isError() const {
        return std::holds_alternative<ErrorType>(valueOrError_m);
    }

    [[nodiscard]] ValueType getValue() const {
        return std::get<ValueType>(valueOrError_m);
    }

    [[nodiscard]] ErrorType getError() const {
        return std::get<ErrorType>(valueOrError_m);
    }

private:
    std::variant<ValueType, ErrorType> valueOrError_m;
};

template<typename ValueType, typename ErrorType>
std::ostream& operator<<(std::ostream& os, const ValueOrError<ValueType, ErrorType>& voe) {
    if (voe.isError()) {
        os << "ERROR=" << voe.getError();
    } else {
        os << "VALUE=" << voe.getValue();
    }
    return os;
}

enum class ERROR_CODE {
    INVALID_STRING,
    NOT_AN_HEX_VALUE,
    VALUE_TOO_LARGE
};

std::ostream& operator<<(std::ostream& os, const ERROR_CODE& code) {
    switch (code) {
        case ERROR_CODE::INVALID_STRING:
            os << "INVALID_STRING";
            break;
        case ERROR_CODE::NOT_AN_HEX_VALUE:
            os << "NOT_AN_HEX_VALUE";
            break;
        case ERROR_CODE::VALUE_TOO_LARGE:
            os << "VALUE_TOO_LARGE";
            break;
    }
    return os;
}

int main() {
    using MyValueOrError = ValueOrError<int, ERROR_CODE>;

    std::cout << std::boolalpha;

    const auto value = MyValueOrError{42};
    std::cout << value << '\n';

    const auto error = MyValueOrError{ERROR_CODE::INVALID_STRING};
    std::cout << error << '\n';
}
Enter fullscreen mode Exit fullscreen mode

This code prints:

VALUE=42
ERROR=INVALID_STRING

Collapse
 
heliobatimarqui profile image
Helio Nunes Santos

Hi Pierre! First all, thank you for reading. The reason why I didn't use std::variant is because it is not available on a freestanding environment. For purposes of demonstration, I made the code compilable in a regular environment and thus used the libraries available in and . On my kernel code, I am having to reimplement it all, as they are not available. I will probably reimplement something on the lines of std::variant when the necessity arises.