@@ -63,10 +63,28 @@ namespace internal
6363 class EraseStaleEntries ;
6464 struct CustomHierarchyData ;
6565
66+ template <typename T_Container>
67+ struct AccessContainer
68+ {
69+ using T_ActualContainer = T_Container;
70+ static T_Container construct ()
71+ {
72+ return T_Container ();
73+ }
74+ static T_ActualContainer &access (T_Container &cont)
75+ {
76+ return cont;
77+ }
78+ static T_ActualContainer const &access (T_Container const &cont)
79+ {
80+ return cont;
81+ }
82+ };
83+
6684 template <
6785 typename T,
6886 typename T_key = std::string,
69- typename T_container = std::map<T_key, T> >
87+ typename T_container = std::map<T_key, T>>
7088 class ContainerData : virtual public AttributableData
7189 {
7290 public:
@@ -75,7 +93,8 @@ namespace internal
7593 /* *
7694 * The wrapped container holding all the actual data, e.g. std::map.
7795 */
78- InternalContainer m_container;
96+ InternalContainer m_container =
97+ AccessContainer<T_container>::construct();
7998
8099 ContainerData () = default;
81100
@@ -85,6 +104,48 @@ namespace internal
85104 ContainerData &operator =(ContainerData const &) = delete ;
86105 ContainerData &operator =(ContainerData &&) = delete ;
87106 };
107+
108+ /*
109+ * This allows to have a Container which references another Container's
110+ * data.
111+ * Reason: Unfortunately, Iteration::meshes and Iteration::particles are
112+ * public members and not methods. This makes it impossible to modify their
113+ * behavior when doing an internal refactoring.
114+ * We would need this now: We want to keep these members for legady and
115+ * shortcut access, but the actual data is now stored as a further group
116+ * in the CustomHierarchy structure. E.g. `iteration.meshes` points to
117+ * the same thing as `iteration["meshes"].
118+ * If we had a method `Iteration::meshes()`, we could simply find that group
119+ * at call time and hand it out to the user.
120+ * Instead, we need to synchronize both objects. At first flush, **if**
121+ * there are meshes defined, all data is moved from `Iteration.meshes` to
122+ * `Iteration["meshes"]. Then, `Iteration.meshes` is set to point at
123+ * `Iteration["meshes"]`, making them go synchronous.
124+ * This is made possible by allowing the use of `internal::ContainerData`
125+ * as internal container type.
126+ * We cannot create them synchronously at construction time since the key
127+ * "meshes" might not be created after all, and `setMeshesPath()` has not
128+ * been called yet, so would not even know the proper key.
129+ */
130+ template <typename T, typename T_key, typename T_Container>
131+ struct AccessContainer <
132+ std::shared_ptr<ContainerData<T, T_key, T_Container>>>
133+ {
134+ using T_Wrapper = std::shared_ptr<ContainerData<T, T_key, T_Container>>;
135+ using T_ActualContainer = T_Container;
136+ static T_Wrapper construct ()
137+ {
138+ return std::make_shared<ContainerData<T, T_key, T_Container>>();
139+ }
140+ static T_ActualContainer &access (T_Wrapper &cont)
141+ {
142+ return cont->m_container ;
143+ }
144+ static T_ActualContainer const &access (T_Wrapper const &cont)
145+ {
146+ return cont->m_container ;
147+ }
148+ };
88149} // namespace internal
89150
90151/* * @brief Map-like container that enforces openPMD requirements and handles IO.
@@ -99,7 +160,7 @@ namespace internal
99160template <
100161 typename T,
101162 typename T_key = std::string,
102- typename T_container = std::map<T_key, T> >
163+ typename T_container = std::map<T_key, T>>
103164class Container : virtual public Attributable
104165{
105166 friend class Iteration ;
@@ -113,9 +174,11 @@ class Container : virtual public Attributable
113174 friend struct internal ::CustomHierarchyData;
114175 friend class CustomHierarchy ;
115176
177+ using AccessContainer = internal::AccessContainer<T_container>;
178+
116179protected:
117180 using ContainerData = internal::ContainerData<T, T_key, T_container>;
118- using InternalContainer = T_container ;
181+ using InternalContainer = typename AccessContainer::T_ActualContainer ;
119182
120183 std::shared_ptr<ContainerData> m_containerData;
121184
@@ -127,12 +190,12 @@ class Container : virtual public Attributable
127190
128191 inline InternalContainer const &container () const
129192 {
130- return m_containerData->m_container ;
193+ return AccessContainer::access ( m_containerData->m_container ) ;
131194 }
132195
133196 inline InternalContainer &container ()
134197 {
135- return m_containerData->m_container ;
198+ return AccessContainer::access ( m_containerData->m_container ) ;
136199 }
137200
138201public:
0 commit comments