DtkGui
DTK Gui 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 <QtCore/qcompilerdetection.h>
8
9// Private member accessor using the explicit template instantiation technique.
10//
11// C++ Standard [temp.explicit]/12 states:
12// "The usual access checking rules do not apply to names used to
13// specify explicit instantiation definitions."
14//
15// This allows passing pointers to private/protected data members and
16// member functions as template arguments in explicit instantiations,
17// bypassing normal access control — without modifying the class definition
18// and without the UB caused by "#define private public".
19//
20// NOTE: These helper structs must be in the SAME namespace as the Tag structs
21// (global namespace, since the macros expand at file scope). If they were in a
22// sub-namespace, the friend definition would create a different function than
23// the friend declaration in the Tag struct, causing undefined-reference errors.
24
25QT_WARNING_PUSH
26QT_WARNING_DISABLE_GCC("-Wnon-template-friend")
27
28template<typename Tag>
30{
31 using MemberPtr = typename Tag::MemberPtr;
32 friend MemberPtr get(Tag) noexcept;
33};
34
35template<typename Tag, typename Tag::MemberPtr Ptr>
37{
38 friend typename Tag::MemberPtr get(Tag) noexcept { return Ptr; }
39};
40
41QT_WARNING_POP
42
43#define D_DECLARE_PRIVATE_MEMBER(TagName, ClassName, Member, MemberType) \
44 struct TagName { \
45 using MemberPtr = MemberType ClassName::*; \
46 friend MemberPtr get(TagName) noexcept; \
47 }; \
48 template struct DtkGuiPrivateAccessorImpl<TagName, &ClassName::Member>
49
50#define D_DECLARE_PRIVATE_METHOD(TagName, ClassName, MethodName, RetType, ...) \
51 struct TagName { \
52 using MemberPtr = RetType (ClassName::*)(__VA_ARGS__); \
53 friend MemberPtr get(TagName) noexcept; \
54 }; \
55 template struct DtkGuiPrivateAccessorImpl<TagName, &ClassName::MethodName>
56
57#define D_DECLARE_PRIVATE_CONST_METHOD(TagName, ClassName, MethodName, RetType, ...) \
58 struct TagName { \
59 using MemberPtr = RetType (ClassName::*)(__VA_ARGS__) const; \
60 friend MemberPtr get(TagName) noexcept; \
61 }; \
62 template struct DtkGuiPrivateAccessorImpl<TagName, &ClassName::MethodName>
63
64// Trampoline: ensures get(tag) is called from a context with no class-scope
65// get() member that might suppress ADL (C++ [basic.lookup.argdep] para 3).
66namespace dtk_private_detail {
67 template<typename Tag>
68 inline typename Tag::MemberPtr access(Tag t) noexcept { return get(t); }
69}
70
71#define D_PRIVATE_MEMBER(obj, tag) ((obj).*dtk_private_detail::access(tag))
72#define D_PRIVATE_CALL(obj, tag, ...) ((obj).*dtk_private_detail::access(tag))(__VA_ARGS__)
Definition dprivateaccessor_p.h:37
Definition dprivateaccessor_p.h:30