LINUX.ORG.RU

История изменений

Исправление Ivan_qrt, (текущая версия) :

Ещё немного поупарывался:

#include <iostream>
#include <magic_enum_utility.hpp>



enum class AllError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
    E3 = 3,
    E4 = 4,
    E7 = 7,
};


template <class T> concept Enum = std::is_enum_v<T>;

template <Enum DST, Enum SRC>
consteval bool check_contains_all() noexcept {
    bool contains_all = true;
    magic_enum::enum_for_each<SRC>([&contains_all](auto val) {
        constexpr SRC choice = val;
        contains_all &= magic_enum::enum_contains<DST>(static_cast<std::underlying_type_t<SRC>>(choice));
    });
    return contains_all;
}

template <Enum DST, Enum SRC>
constexpr DST err_cast(SRC src) noexcept {
    static_assert(check_contains_all<DST, SRC>());
    return static_cast<DST>(src);
}



template <Enum T>
struct [[nodiscard]] Error {
    using ErrorEnum = T;
    static_assert(check_contains_all<AllError, ErrorEnum>());

    const ErrorEnum error;

    constexpr Error(ErrorEnum err) noexcept: error{err} {}
    constexpr Error(std::underlying_type_t<ErrorEnum> ec) noexcept: error{ec} {}

    template <Enum E>
    constexpr Error(E err) noexcept: error{err_cast<ErrorEnum>(err)} {}
    template <Enum E>
    constexpr Error(Error<E> err) noexcept: error{err_cast<ErrorEnum>(err.error)} {}

    constexpr operator bool() const noexcept { return error != ErrorEnum::Success; } 
};



enum class FooError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
#ifdef WITH_ERROR
    E7 = 7,
#endif
};

Error<FooError> foo() { return FooError::E2; }



enum class BarError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
    E3 = 3,
    E4 = 4,
#ifdef WITH_ERROR2
    E9 = 9,
#endif
};


Error<BarError> bar() {
    Error<BarError> err = foo();
    if (err) {
        return err;
    }
    // ...
    return BarError::Success;
}



int main() {
    auto err1 = foo();
    std::cout << magic_enum::enum_name(err1.error) << std::endl;
    auto err2 = bar();
    std::cout << magic_enum::enum_name(err2.error) << std::endl;
}

Исправление Ivan_qrt, :

Ещё немного поупарывался:

#include <iostream>
#include <magic_enum_utility.hpp>



enum class AllError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
    E3 = 3,
    E4 = 4,
    E7 = 7,
};


template <class T> concept Enum = std::is_enum_v<T>;

template <Enum DST, Enum SRC>
consteval bool check_contains_all() noexcept {
    bool contains_all = true;
    magic_enum::enum_for_each<SRC>([&contains_all](auto val) {
        constexpr SRC choice = val;
        contains_all &= magic_enum::enum_contains<DST>(static_cast<std::underlying_type_t<SRC>>(choice));
    });
    return contains_all;
}

template <Enum DST, Enum SRC>
constexpr DST err_cast(SRC src) noexcept {
    static_assert(check_contains_all<DST, SRC>());
    return static_cast<DST>(src);
}



template <Enum T>
struct Error {
    using ErrorEnum = T;
    static_assert(check_contains_all<AllError, ErrorEnum>());

    const ErrorEnum error;

    constexpr Error(ErrorEnum err) noexcept: error{err} {}
    constexpr Error(std::underlying_type_t<ErrorEnum> ec) noexcept: error{ec} {}

    template <Enum E>
    constexpr Error(E err) noexcept: error{err_cast<ErrorEnum>(err)} {}
    template <Enum E>
    constexpr Error(Error<E> err) noexcept: error{err_cast<ErrorEnum>(err.error)} {}

    constexpr operator bool() const noexcept { return error != ErrorEnum::Success; } 
};



enum class FooError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
#ifdef WITH_ERROR
    E7 = 7,
#endif
};

Error<FooError> foo() { return FooError::E2; }



enum class BarError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
    E3 = 3,
    E4 = 4,
#ifdef WITH_ERROR2
    E9 = 9,
#endif
};


Error<BarError> bar() {
    Error<BarError> err = foo();
    if (err) {
        return err;
    }
    // ...
    return BarError::Success;
}



int main() {
    auto err1 = foo();
    std::cout << magic_enum::enum_name(err1.error) << std::endl;
    auto err2 = bar();
    std::cout << magic_enum::enum_name(err2.error) << std::endl;
}

Исходная версия Ivan_qrt, :

Ещё немного поупарывался:

#include <iostream>
#include <magic_enum_utility.hpp>


////////////////////////////////////////////////////////////////////////////////////////////////////


enum class AllError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
    E3 = 3,
    E4 = 4,
    E7 = 7,
};


////////////////////////////////////////////////////////////////////////////////////////////////////


template <class T> concept Enum = std::is_enum_v<T>;

template <Enum DST, Enum SRC>
consteval bool check_contains_all() noexcept {
    bool contains_all = true;
    magic_enum::enum_for_each<SRC>([&contains_all](auto val) {
        constexpr SRC choice = val;
        contains_all &= magic_enum::enum_contains<DST>(static_cast<std::underlying_type_t<SRC>>(choice));
    });
    return contains_all;
}

template <Enum DST, Enum SRC>
constexpr DST err_cast(SRC src) noexcept {
    static_assert(check_contains_all<DST, SRC>());
    return static_cast<DST>(src);
}



template <Enum T>
struct Error {
    using ErrorEnum = T;
    static_assert(check_contains_all<AllError, ErrorEnum>());

    const ErrorEnum error;

    constexpr Error(ErrorEnum err) noexcept: error{err} {}
    constexpr Error(std::underlying_type_t<ErrorEnum> ec) noexcept: error{ec} {}

    template <Enum E>
    constexpr Error(E err) noexcept: error{err_cast<ErrorEnum>(err)} {}
    template <Enum E>
    constexpr Error(Error<E> err) noexcept: error{err_cast<ErrorEnum>(err.error)} {}

    constexpr operator bool() const noexcept { return error != ErrorEnum::Success; } 
};


////////////////////////////////////////////////////////////////////////////////////////////////////


enum class FooError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
#ifdef WITH_ERROR
    E7 = 7,
#endif
};

Error<FooError> foo() { return FooError::E2; }



enum class BarError: int {
    Success = 0,
    E1 = 1,
    E2 = 2,
    E3 = 3,
    E4 = 4,
#ifdef WITH_ERROR2
    E9 = 9,
#endif
};


Error<BarError> bar() {
    Error<BarError> err = foo();
    if (err) {
        return err;
    }
    // ...
    return BarError::Success;
}



int main() {
    auto err1 = foo();
    std::cout << magic_enum::enum_name(err1.error) << std::endl;
    auto err2 = bar();
    std::cout << magic_enum::enum_name(err2.error) << std::endl;
}