DtkDeclarative
DTK Declarative module
载入中...
搜索中...
未找到
dprivateaccessor_p.h
1// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5#pragma once
6
7#include <cstddef>
8#include <QtCore/qcompilerdetection.h>
9
10// Private member accessor using the explicit template instantiation technique.
11//
12// C++ Standard [temp.explicit]/12 states:
13// "The usual access checking rules do not apply to names used to
14// specify explicit instantiation definitions."
15//
16// This allows passing pointers to private/protected data members and
17// member functions as template arguments in explicit instantiations,
18// bypassing normal access control — without modifying the class definition
19// and without the UB caused by "#define private public".
20//
21// NOTE: These helper structs must be in the SAME namespace as the Tag structs
22// (global namespace, since the macros expand at file scope). If they were in a
23// sub-namespace, the friend definition would create a different function than
24// the friend declaration in the Tag struct, causing undefined-reference errors.
25
26QT_WARNING_PUSH
27QT_WARNING_DISABLE_GCC("-Wnon-template-friend")
28
29template<typename Tag>
31{
32 using MemberPtr = typename Tag::MemberPtr;
33 friend constexpr MemberPtr get(Tag) noexcept;
34};
35
36template<typename Tag, typename Tag::MemberPtr Ptr>
38{
39 friend constexpr typename Tag::MemberPtr get(Tag) noexcept { return Ptr; }
40};
41
42QT_WARNING_POP
43
44#define D_DECLARE_PRIVATE_MEMBER(TagName, ClassName, Member, MemberType) \
45 struct TagName { \
46 using MemberPtr = MemberType ClassName::*; \
47 friend constexpr MemberPtr get(TagName) noexcept; \
48 }; \
49 template struct DtkDeclarativePrivateAccessorImpl<TagName, &ClassName::Member>
50
51#define D_DECLARE_PRIVATE_METHOD(TagName, ClassName, MethodName, RetType, ...) \
52 struct TagName { \
53 using MemberPtr = RetType (ClassName::*)(__VA_ARGS__); \
54 friend constexpr MemberPtr get(TagName) noexcept; \
55 }; \
56 template struct DtkDeclarativePrivateAccessorImpl<TagName, &ClassName::MethodName>
57
58#define D_DECLARE_PRIVATE_CONST_METHOD(TagName, ClassName, MethodName, RetType, ...) \
59 struct TagName { \
60 using MemberPtr = RetType (ClassName::*)(__VA_ARGS__) const; \
61 friend constexpr MemberPtr get(TagName) noexcept; \
62 }; \
63 template struct DtkDeclarativePrivateAccessorImpl<TagName, &ClassName::MethodName>
64
65#define D_DECLARE_PRIVATE_BITFIELD(TagName, ClassName, PrevMember, PrevMemberType, BfStorageType) \
66 struct TagName { \
67 using MemberPtr = PrevMemberType ClassName::*; \
68 friend constexpr MemberPtr get(TagName) noexcept; \
69 }; \
70 template struct DtkDeclarativePrivateAccessorImpl<TagName, &ClassName::PrevMember>; \
71 struct TagName##_bf_layout_mirror { PrevMemberType prev; BfStorageType storage; }; \
72 struct TagName##_Bits { \
73 static constexpr std::size_t kOffset = \
74 __builtin_offsetof(TagName##_bf_layout_mirror, storage) - \
75 __builtin_offsetof(TagName##_bf_layout_mirror, prev); \
76 static BfStorageType *storagePtr(ClassName *obj) noexcept { \
77 PrevMemberType &prev_ref = (*obj).*get(TagName{}); \
78 return reinterpret_cast<BfStorageType*>( \
79 reinterpret_cast<char *>(&prev_ref) + kOffset); \
80 } \
81 static const BfStorageType *storagePtr(const ClassName *obj) noexcept { \
82 return storagePtr(const_cast<ClassName *>(obj)); \
83 } \
84 static bool getBit(const ClassName *obj, unsigned bit) noexcept { \
85 return (*storagePtr(obj) >> bit) & BfStorageType{1}; \
86 } \
87 static void setBit(ClassName *obj, unsigned bit, bool val) noexcept { \
88 BfStorageType *p = storagePtr(obj); \
89 if (val) *p |= (BfStorageType{1} << bit); \
90 else *p &= ~(BfStorageType{1} << bit); \
91 } \
92 }
93
94// Trampoline: ensures get(tag) is called from a context with no class-scope
95// get() member that might suppress ADL (C++ [basic.lookup.argdep] para 3).
96namespace dtk_private_detail {
97 template<typename Tag>
98 inline typename Tag::MemberPtr access(Tag t) noexcept { return get(t); }
99}
100
101#define D_PRIVATE_MEMBER(obj, tag) ((obj).*dtk_private_detail::access(tag))
102#define D_PRIVATE_CALL(obj, tag, ...) ((obj).*dtk_private_detail::access(tag))(__VA_ARGS__)
103#define D_PRIVATE_BF_GET(obj, TagName, bit_pos) \
104 TagName##_Bits::getBit(&(obj), (bit_pos))
105#define D_PRIVATE_BF_SET(obj, TagName, bit_pos, val) \
106 TagName##_Bits::setBit(&(obj), (bit_pos), (val))
Definition dprivateaccessor_p.h:38
Definition dprivateaccessor_p.h:31