История изменений
Исправление 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;
}