Merge pull request #9633 from Pokechu22/BitfieldExtract-pointer-to-member

Change BitfieldExtract to use a pointer to the bitfield member
This commit is contained in:
Léo Lam
2021-05-08 00:21:15 +02:00
committed by GitHub
8 changed files with 164 additions and 79 deletions

View File

@ -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

View File

@ -125,6 +125,7 @@ add_library(common
TraversalClient.cpp
TraversalClient.h
TraversalProto.h
TypeUtils.h
UPnP.cpp
UPnP.h
VariantUtil.h

View File

@ -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