Merge 845fecff22
into 53b54406bd
This commit is contained in:
commit
59a7c75c1c
|
@ -114,21 +114,17 @@
|
|||
*/
|
||||
#pragma pack(1)
|
||||
template <std::size_t position, std::size_t bits, typename T,
|
||||
// StorageType is T for non-enum types and the underlying type of T if
|
||||
// T is an enumeration. Note that T is wrapped within an enable_if in the
|
||||
// former case to workaround compile errors which arise when using
|
||||
// std::underlying_type<T>::type directly.
|
||||
typename StorageType = typename std::conditional_t<
|
||||
std::is_enum<T>::value, std::underlying_type<T>, std::enable_if<true, T>>::type>
|
||||
// StorageType is T for non-enum or the underlying-type for an enum.
|
||||
typename StorageType = std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>,
|
||||
std::type_identity<T>>::type>
|
||||
struct BitField
|
||||
{
|
||||
private:
|
||||
public:
|
||||
// This constructor might be considered ambiguous:
|
||||
// Would it initialize the storage or just the bitfield?
|
||||
// Hence, delete it. Use the assignment operator to set bitfield values!
|
||||
BitField(T val) = delete;
|
||||
|
||||
public:
|
||||
// Force default constructor to be created
|
||||
// so that we can use this within unions
|
||||
constexpr BitField() = default;
|
||||
|
@ -212,26 +208,22 @@ class BitFieldArrayIterator;
|
|||
|
||||
#pragma pack(1)
|
||||
template <std::size_t position, std::size_t bits, std::size_t size, typename T,
|
||||
// StorageType is T for non-enum types and the underlying type of T if
|
||||
// T is an enumeration. Note that T is wrapped within an enable_if in the
|
||||
// former case to workaround compile errors which arise when using
|
||||
// std::underlying_type<T>::type directly.
|
||||
typename StorageType = typename std::conditional_t<
|
||||
std::is_enum<T>::value, std::underlying_type<T>, std::enable_if<true, T>>::type>
|
||||
// StorageType is T for non-enum or the underlying-type for an enum.
|
||||
typename StorageType = std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>,
|
||||
std::type_identity<T>>::type>
|
||||
struct BitFieldArray
|
||||
{
|
||||
public:
|
||||
using Ref = BitFieldArrayRef<position, bits, size, T, StorageType>;
|
||||
using ConstRef = BitFieldArrayConstRef<position, bits, size, T, StorageType>;
|
||||
using Iterator = BitFieldArrayIterator<position, bits, size, T, StorageType>;
|
||||
using ConstIterator = BitFieldArrayConstIterator<position, bits, size, T, StorageType>;
|
||||
|
||||
private:
|
||||
// This constructor might be considered ambiguous:
|
||||
// Would it initialize the storage or just the bitfield?
|
||||
// Hence, delete it. Use the assignment operator to set bitfield values!
|
||||
BitFieldArray(T val) = delete;
|
||||
|
||||
public:
|
||||
// Force default constructor to be created
|
||||
// so that we can use this within unions
|
||||
constexpr BitFieldArray() = default;
|
||||
|
@ -244,7 +236,6 @@ public:
|
|||
// code expects that this class is trivially copyable.
|
||||
BitFieldArray& operator=(const BitFieldArray&) = delete;
|
||||
|
||||
public:
|
||||
constexpr bool IsSigned() const { return std::is_signed<T>(); }
|
||||
constexpr std::size_t StartBit() const { return position; }
|
||||
constexpr std::size_t NumBits() const { return bits; }
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <bit>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
@ -117,8 +116,8 @@ constexpr Result ExtractBits(const T src) noexcept
|
|||
template <typename T>
|
||||
constexpr bool IsValidLowMask(const T mask) noexcept
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "Mask must be an integral type.");
|
||||
static_assert(std::is_unsigned<T>::value, "Signed masks can introduce hard to find bugs.");
|
||||
static_assert(std::is_integral_v<T>, "Mask must be an integral type.");
|
||||
static_assert(std::is_unsigned_v<T>, "Signed masks can introduce hard to find bugs.");
|
||||
|
||||
// Can be efficiently determined without looping or bit counting. It's the counterpart
|
||||
// to https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
|
||||
|
@ -138,11 +137,10 @@ public:
|
|||
explicit BitCastPtrType(PtrType* ptr) : m_ptr(ptr) {}
|
||||
|
||||
// Enable operator= only for pointers to non-const data
|
||||
template <typename S>
|
||||
inline typename std::enable_if<std::is_same<S, T>() && !std::is_const<PtrType>()>::type
|
||||
operator=(const S& source)
|
||||
auto& operator=(const T& source) requires(!std::is_const_v<PtrType>)
|
||||
{
|
||||
std::memcpy(m_ptr, &source, sizeof(source));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline operator T() const
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "Common/EnumMap.h"
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/Inline.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
// Wrapper class
|
||||
class PointerWrap
|
||||
|
@ -195,13 +194,15 @@ public:
|
|||
DoArray(x.data(), static_cast<u32>(x.size()));
|
||||
}
|
||||
|
||||
template <typename T, typename std::enable_if_t<std::is_trivially_copyable_v<T>, int> = 0>
|
||||
template <typename T>
|
||||
requires(std::is_trivially_copyable_v<T>)
|
||||
void DoArray(T* x, u32 count)
|
||||
{
|
||||
DoVoid(x, count * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T, typename std::enable_if_t<!std::is_trivially_copyable_v<T>, int> = 0>
|
||||
template <typename T>
|
||||
requires(!std::is_trivially_copyable_v<T>)
|
||||
void DoArray(T* x, u32 count)
|
||||
{
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
|
|
|
@ -6,21 +6,14 @@
|
|||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Config/Enums.h"
|
||||
#include "Common/TypeUtils.h"
|
||||
|
||||
namespace Config
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// std::underlying_type may only be used with enum types, so make sure T is an enum type first.
|
||||
template <typename T>
|
||||
using UnderlyingType = typename std::enable_if_t<std::is_enum<T>{}, std::underlying_type<T>>::type;
|
||||
} // namespace detail
|
||||
|
||||
struct Location
|
||||
{
|
||||
System system{};
|
||||
|
@ -54,8 +47,7 @@ public:
|
|||
|
||||
// Make it easy to convert Info<Enum> into Info<UnderlyingType<Enum>>
|
||||
// so that enum settings can still easily work with code that doesn't care about the enum values.
|
||||
template <typename Enum,
|
||||
std::enable_if_t<std::is_same<T, detail::UnderlyingType<Enum>>::value>* = nullptr>
|
||||
template <Common::TypedEnum<T> Enum>
|
||||
Info(const Info<Enum>& other)
|
||||
{
|
||||
*this = other;
|
||||
|
@ -80,8 +72,7 @@ public:
|
|||
|
||||
// Make it easy to convert Info<Enum> into Info<UnderlyingType<Enum>>
|
||||
// so that enum settings can still easily work with code that doesn't care about the enum values.
|
||||
template <typename Enum,
|
||||
std::enable_if_t<std::is_same<T, detail::UnderlyingType<Enum>>::value>* = nullptr>
|
||||
template <Common::TypedEnum<T> Enum>
|
||||
Info<T>& operator=(const Info<Enum>& other)
|
||||
{
|
||||
m_location = other.GetLocation();
|
||||
|
|
|
@ -23,7 +23,8 @@ struct DefaultState
|
|||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
|
||||
template <typename T>
|
||||
requires(!Common::Enum<T>)
|
||||
std::optional<T> TryParse(const std::string& str_value)
|
||||
{
|
||||
T value;
|
||||
|
@ -32,7 +33,7 @@ std::optional<T> TryParse(const std::string& str_value)
|
|||
return value;
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
|
||||
template <Common::Enum T>
|
||||
std::optional<T> TryParse(const std::string& str_value)
|
||||
{
|
||||
const auto result = TryParse<std::underlying_type_t<T>>(str_value);
|
||||
|
|
|
@ -42,11 +42,10 @@
|
|||
* constexpr formatter() : EnumFormatter(names) {}
|
||||
* };
|
||||
*/
|
||||
template <auto last_member>
|
||||
template <Common::Enum auto last_member>
|
||||
class EnumFormatter
|
||||
{
|
||||
using T = decltype(last_member);
|
||||
static_assert(std::is_enum_v<T>);
|
||||
|
||||
public:
|
||||
constexpr auto parse(fmt::format_parse_context& ctx)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Common/TypeUtils.h"
|
||||
|
||||
|
@ -15,11 +14,10 @@ namespace Common
|
|||
{
|
||||
// A type that allows lookup of values associated with an enum as the key.
|
||||
// Designed for enums whose numeric values start at 0 and increment continuously with few gaps.
|
||||
template <typename V, auto last_member>
|
||||
template <typename V, Common::Enum auto last_member>
|
||||
class EnumMap final
|
||||
{
|
||||
using T = decltype(last_member);
|
||||
static_assert(std::is_enum_v<T>);
|
||||
static constexpr size_t s_size = static_cast<size_t>(last_member) + 1;
|
||||
|
||||
using array_type = std::array<V, s_size>;
|
||||
|
@ -34,8 +32,9 @@ public:
|
|||
constexpr EnumMap& operator=(EnumMap&& other) = default;
|
||||
|
||||
// Constructor that accepts exactly size Vs (enforcing that all must be specified).
|
||||
template <typename... T, typename = std::enable_if_t<Common::IsNOf<V, s_size, T...>::value>>
|
||||
constexpr EnumMap(T... values) : m_array{static_cast<V>(values)...}
|
||||
template <typename... T>
|
||||
constexpr EnumMap(T... values) requires(Common::IsNOf<V, s_size, T...>::value)
|
||||
: m_array{static_cast<V>(values)...}
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -3,26 +3,25 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/EnumUtils.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "Common/TypeUtils.h"
|
||||
|
||||
sf::Packet& operator>>(sf::Packet& packet, Common::BigEndianValue<u16>& data);
|
||||
sf::Packet& operator>>(sf::Packet& packet, Common::BigEndianValue<u32>& data);
|
||||
sf::Packet& operator>>(sf::Packet& packet, Common::BigEndianValue<u64>& data);
|
||||
|
||||
template <typename Enum, std::enable_if_t<std::is_enum_v<Enum>>* = nullptr>
|
||||
template <Common::Enum Enum>
|
||||
sf::Packet& operator<<(sf::Packet& packet, Enum e)
|
||||
{
|
||||
using Underlying = std::underlying_type_t<Enum>;
|
||||
packet << static_cast<Underlying>(e);
|
||||
packet << Common::ToUnderlying(e);
|
||||
return packet;
|
||||
}
|
||||
|
||||
template <typename Enum, std::enable_if_t<std::is_enum_v<Enum>>* = nullptr>
|
||||
template <Common::Enum Enum>
|
||||
sf::Packet& operator>>(sf::Packet& packet, Enum& e)
|
||||
{
|
||||
using Underlying = std::underlying_type_t<Enum>;
|
||||
|
|
|
@ -70,8 +70,8 @@ static_assert(!std::is_same_v<ObjectType<&Bar::c>, Bar>);
|
|||
|
||||
// Template for checking if Types is count occurrences of T.
|
||||
template <typename T, size_t count, typename... Ts>
|
||||
struct IsNOf : std::integral_constant<bool, std::conjunction_v<std::is_convertible<Ts, T>...> &&
|
||||
sizeof...(Ts) == count>
|
||||
struct IsNOf : std::bool_constant<std::conjunction_v<std::is_convertible<Ts, T>...> &&
|
||||
sizeof...(Ts) == count>
|
||||
{
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue