summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-05-08 00:21:15 +0200
committerGitHub <noreply@github.com>2021-05-08 00:21:15 +0200
commita6f6211ddeaa87fee5009df7ba467ef733fa3fcf (patch)
treef0677c763f4960d8373b2bb424a4d93ead8a0df3 /Source/Core/Common
parent049b92b7ef51b8aaa0f3a9370c3e8bccd44d185b (diff)
parent0f7c9ef76783ac8c93d3fb099b43cede1e6915f4 (diff)
Merge pull request #9633 from Pokechu22/BitfieldExtract-pointer-to-member
Change BitfieldExtract to use a pointer to the bitfield member
Diffstat (limited to 'Source/Core/Common')
-rw-r--r--Source/Core/Common/BitField.h4
-rw-r--r--Source/Core/Common/CMakeLists.txt1
-rw-r--r--Source/Core/Common/TypeUtils.h70
3 files changed, 73 insertions, 2 deletions
diff --git a/Source/Core/Common/BitField.h b/Source/Core/Common/BitField.h
index e7af066d2f..b3a3a41cbc 100644
--- a/Source/Core/Common/BitField.h
+++ b/Source/Core/Common/BitField.h
@@ -155,8 +155,8 @@ public:
constexpr T Value() const { return Value(std::is_signed<T>()); }
constexpr operator T() const { return Value(); }
- constexpr std::size_t StartBit() const { return position; }
- constexpr std::size_t NumBits() const { return bits; }
+ static constexpr std::size_t StartBit() { return position; }
+ static constexpr std::size_t NumBits() { return bits; }
private:
// Unsigned version of StorageType
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 4846601305..fc955c1487 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -125,6 +125,7 @@ add_library(common
TraversalClient.cpp
TraversalClient.h
TraversalProto.h
+ TypeUtils.h
UPnP.cpp
UPnP.h
VariantUtil.h
diff --git a/Source/Core/Common/TypeUtils.h b/Source/Core/Common/TypeUtils.h
new file mode 100644
index 0000000000..c87bd3f546
--- /dev/null
+++ b/Source/Core/Common/TypeUtils.h
@@ -0,0 +1,70 @@
+// Copyright 2021 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <type_traits>
+
+namespace Common
+{
+template <typename>
+struct MemberPointerInfo;
+// Helper to get information about a pointer to a data member.
+// See https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members
+// This template takes the type for a member pointer.
+template <typename M, typename O>
+struct MemberPointerInfo<M O::*>
+{
+ using MemberType = M;
+ using ObjectType = O;
+};
+
+// This template takes a specific member pointer.
+template <auto member_pointer>
+using MemberType = typename MemberPointerInfo<decltype(member_pointer)>::MemberType;
+
+// This template takes a specific member pointer.
+template <auto member_pointer>
+using ObjectType = typename MemberPointerInfo<decltype(member_pointer)>::ObjectType;
+
+namespace detail
+{
+template <int x>
+struct Data
+{
+ static constexpr int GetX() { return x; }
+};
+struct Foo
+{
+ Data<1> a;
+ Data<2> b;
+ int c;
+};
+struct Bar : Foo
+{
+ int d;
+};
+
+static_assert(std::is_same_v<MemberType<&Foo::a>, Data<1>>);
+static_assert(MemberType<&Foo::a>::GetX() == 1);
+static_assert(std::is_same_v<MemberType<&Foo::b>, Data<2>>);
+static_assert(MemberType<&Foo::b>::GetX() == 2);
+static_assert(std::is_same_v<MemberType<&Foo::c>, int>);
+
+static_assert(std::is_same_v<ObjectType<&Foo::a>, Foo>);
+static_assert(std::is_same_v<ObjectType<&Foo::b>, Foo>);
+static_assert(std::is_same_v<ObjectType<&Foo::c>, Foo>);
+
+static_assert(std::is_same_v<MemberType<&Foo::c>, MemberPointerInfo<int Foo::*>::MemberType>);
+static_assert(std::is_same_v<ObjectType<&Foo::c>, MemberPointerInfo<int Foo::*>::ObjectType>);
+
+static_assert(std::is_same_v<MemberType<&Bar::c>, int>);
+static_assert(std::is_same_v<MemberType<&Bar::d>, int>);
+
+static_assert(std::is_same_v<ObjectType<&Bar::d>, Bar>);
+// Somewhat unexpected behavior:
+static_assert(std::is_same_v<ObjectType<&Bar::c>, Foo>);
+static_assert(!std::is_same_v<ObjectType<&Bar::c>, Bar>);
+} // namespace detail
+} // namespace Common