Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
ObjectFieldUtilities.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Memory_ObjectFieldUtilities_h_
5#define _Stroika_Foundation_Memory_ObjectFieldUtilities_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <cstddef>
10
11/**
12 * \file
13 *
14 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
15 *
16 */
17
18namespace Stroika::Foundation::Memory {
19
20 using namespace std;
21
22 /**
23 * Given an objects field (given by pointer to member) and that owned object, run 'offsetof' backwards
24 * to get the original owning object.
25 *
26 * \par Example Usage
27 * \code
28 * void test ();
29 * struct X1 {
30 * int a;
31 * int b;
32 * };
33 * struct X2 {
34 * public:
35 * int a;
36 * private:
37 * int b;
38 * private:
39 * friend void test();
40 * };
41 * void DoTest ()
42 * {
43 * {
44 * X1 t;
45 * static_assert (is_standard_layout_v<X1>);
46 * void* aAddr = &t.a;
47 * void* bAddr = &t.b;
48 * assert (GetObjectOwningField (aAddr, &X1::a) == &t);
49 * assert (GetObjectOwningField (bAddr, &X1::b) == &t);
50 * }
51 * {
52 * // Check and warning but since X2 is not standard layout, this isn't guaranteed to work
53 * X2 t;
54 * static_assert (not is_standard_layout_v<X2>);
55 * void* aAddr = &t.a;
56 * void* bAddr = &t.b;
57 * assert (GetObjectOwningField (aAddr, &X2::a) == &t);
58 * assert (GetObjectOwningField (bAddr, &X2::b) == &t);
59 * }
60 * }
61 * \endcode
62 *
63 * \par Example Usage
64 * \code
65 * struct Header {
66 * ReadOnlyProperty<int> p {[] (const auto* property) {
67 * const Header* h = GetObjectOwningField(property, &Header::p);
68 * // This should recover the pointer to the object Header from the pointer to its field 'p';
69 * }};
70 * \endcode
71 *
72 * \note - for this to work - OUTER_OBJECT (in the above example: Header) must be of standard_layout type according
73 * to c++ standard, but I'm not sure what todo otherwise, it it seems to work otherwise.
74 * Posted to stackoverflow to find a better, more portable way: https://stackoverflow.com/questions/65940393/c-why-the-restriction-on-offsetof-for-non-standard-layout-objects-or-how-t
75 *
76 * See Docs on Memory::OffsetOf() - experiments to find a way to do this portably.
77 */
78 template <typename APPARENT_MEMBER_TYPE, typename OUTER_OBJECT, typename AGGREGATED_OBJECT_TYPE>
79 OUTER_OBJECT* GetObjectOwningField (APPARENT_MEMBER_TYPE* aggregatedMember, AGGREGATED_OBJECT_TYPE (OUTER_OBJECT::* aggregatedPtrToMember));
80 template <typename APPARENT_MEMBER_TYPE, typename OUTER_OBJECT, typename AGGREGATED_OBJECT_TYPE>
81 const OUTER_OBJECT* GetObjectOwningField (const APPARENT_MEMBER_TYPE* aggregatedMember,
82 AGGREGATED_OBJECT_TYPE (OUTER_OBJECT::* aggregatedPtrToMember));
83
84}
85
86/*
87 ********************************************************************************
88 ***************************** Implementation Details ***************************
89 ********************************************************************************
90 */
91#include "ObjectFieldUtilities.inl"
92
93#endif /*_Stroika_Foundation_Memory_ObjectFieldUtilities_h_*/
OUTER_OBJECT * GetObjectOwningField(APPARENT_MEMBER_TYPE *aggregatedMember, AGGREGATED_OBJECT_TYPE(OUTER_OBJECT::*aggregatedPtrToMember))
STL namespace.