common/swap: add swap template for enum

This commit is contained in:
Weiyi Wang 2018-09-21 19:53:14 -04:00 committed by fearlessTobi
parent 72c70d6808
commit 94bc48dd78

View File

@ -17,6 +17,8 @@
#pragma once #pragma once
#include <type_traits>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#include <cstdlib> #include <cstdlib>
#elif defined(__linux__) #elif defined(__linux__)
@ -605,6 +607,44 @@ struct swap_double_t {
} }
}; };
template <typename T>
struct swap_enum_t {
static_assert(std::is_enum_v<T>);
using base = std::underlying_type_t<T>;
public:
swap_enum_t() = default;
swap_enum_t(const T& v) : value(swap(v)) {}
swap_enum_t& operator=(const T& v) {
value = swap(v);
return *this;
}
operator T() const {
return swap(value);
}
explicit operator base() const {
return static_cast<base>(swap(value));
}
protected:
T value{};
// clang-format off
using swap_t = std::conditional_t<
std::is_same_v<base, u16>, swap_16_t<u16>, std::conditional_t<
std::is_same_v<base, s16>, swap_16_t<s16>, std::conditional_t<
std::is_same_v<base, u32>, swap_32_t<u32>, std::conditional_t<
std::is_same_v<base, s32>, swap_32_t<s32>, std::conditional_t<
std::is_same_v<base, u64>, swap_64_t<u64>, std::conditional_t<
std::is_same_v<base, s64>, swap_64_t<s64>, void>>>>>>;
// clang-format on
static T swap(T x) {
return static_cast<T>(swap_t::swap(static_cast<base>(x)));
}
};
#if COMMON_LITTLE_ENDIAN #if COMMON_LITTLE_ENDIAN
using u16_le = u16; using u16_le = u16;
using u32_le = u32; using u32_le = u32;
@ -614,6 +654,9 @@ using s16_le = s16;
using s32_le = s32; using s32_le = s32;
using s64_le = s64; using s64_le = s64;
template <typename T>
using enum_le = std::enable_if_t<std::is_enum_v<T>, T>;
using float_le = float; using float_le = float;
using double_le = double; using double_le = double;
@ -626,6 +669,9 @@ using s32_be = swap_struct_t<s32, swap_32_t<s32>>;
using u16_be = swap_struct_t<u16, swap_16_t<u16>>; using u16_be = swap_struct_t<u16, swap_16_t<u16>>;
using s16_be = swap_struct_t<s16, swap_16_t<s16>>; using s16_be = swap_struct_t<s16, swap_16_t<s16>>;
template <typename T>
using enum_be = swap_enum_t<T>;
using float_be = swap_struct_t<float, swap_float_t<float>>; using float_be = swap_struct_t<float, swap_float_t<float>>;
using double_be = swap_struct_t<double, swap_double_t<double>>; using double_be = swap_struct_t<double, swap_double_t<double>>;
#else #else
@ -639,6 +685,9 @@ using s32_le = swap_struct_t<s32, swap_32_t<s32>>;
using u16_le = swap_struct_t<u16, swap_16_t<u16>>; using u16_le = swap_struct_t<u16, swap_16_t<u16>>;
using s16_le = swap_struct_t<s16, swap_16_t<s16>>; using s16_le = swap_struct_t<s16, swap_16_t<s16>>;
template <typename T>
using enum_le = swap_enum_t<T>;
using float_le = swap_struct_t<float, swap_float_t<float>>; using float_le = swap_struct_t<float, swap_float_t<float>>;
using double_le = swap_struct_t<double, swap_double_t<double>>; using double_le = swap_struct_t<double, swap_double_t<double>>;
@ -650,6 +699,9 @@ using s16_be = s16;
using s32_be = s32; using s32_be = s32;
using s64_be = s64; using s64_be = s64;
template <typename T>
using enum_be = std::enable_if_t<std::is_enum_v<T>, T>;
using float_be = float; using float_be = float;
using double_be = double; using double_be = double;