11#pragma once
22
33#include " openPMD/IO/Access.hpp"
4+ #include < iostream>
45#include < type_traits>
56
67namespace openPMD ::detail
@@ -27,6 +28,95 @@ using CallResult_t = typename IsCallable<F>::type;
2728
2829namespace openPMD ::internal
2930{
31+ template <typename , typename , typename >
32+ struct ConfigAttributeWithSetter ;
33+
34+ template <typename Child, typename GetDefaultValue>
35+ struct ConfigAttribute
36+ {
37+ using DefaultValue = detail::CallResult_t<GetDefaultValue>;
38+ template <typename S>
39+ using SetterType = Child &(
40+ Child::
41+ *)(std::conditional_t <
42+ std::is_void_v<S>,
43+ std::remove_reference_t <detail::CallResult_t<GetDefaultValue>>,
44+ S>);
45+
46+ Child &child;
47+ char const *attrName;
48+ GetDefaultValue &&getDefaultValue;
49+
50+ ConfigAttribute (
51+ Child &child_in,
52+ char const *attrName_in,
53+ GetDefaultValue &&getDefaultValue_in)
54+ : child(child_in)
55+ , attrName(attrName_in)
56+ , getDefaultValue(std::forward<GetDefaultValue>(getDefaultValue_in))
57+ {}
58+
59+ ConfigAttribute (ConfigAttribute const &) = delete ;
60+ ConfigAttribute (ConfigAttribute &&) = default ;
61+
62+ ConfigAttribute &operator =(ConfigAttribute const &) = delete ;
63+ ConfigAttribute &operator =(ConfigAttribute &&) = default ;
64+
65+ template <typename S = void >
66+ auto withSetter (SetterType<S>)
67+ && -> ConfigAttributeWithSetter<Child, GetDefaultValue, SetterType<S>>;
68+
69+ ~ConfigAttribute ()
70+ {
71+ run ();
72+ }
73+
74+ void run ()
75+ {
76+ if (child.containsAttribute (attrName))
77+ {
78+ return ;
79+ }
80+ set (get ());
81+ }
82+
83+ virtual void set (DefaultValue &&val)
84+ {
85+ std::cout << " USING PARENT SETTER" << std::endl;
86+ child.setAttribute (attrName, std::forward<DefaultValue>(val));
87+ }
88+
89+ auto get () -> DefaultValue
90+ {
91+ if constexpr (detail::IsCallable_v<GetDefaultValue>)
92+ {
93+ return std::forward<GetDefaultValue>(getDefaultValue)();
94+ }
95+ else
96+ {
97+ return std::forward<GetDefaultValue>(getDefaultValue);
98+ }
99+ }
100+ };
101+
102+ template <typename Child, typename GetDefaultValue, typename SetDefaultValue>
103+ struct ConfigAttributeWithSetter : ConfigAttribute<Child, GetDefaultValue>
104+ {
105+ using parent_t = ConfigAttribute<Child, GetDefaultValue>;
106+ using DefaultValue = typename parent_t ::DefaultValue;
107+
108+ ConfigAttributeWithSetter (parent_t &&par, SetDefaultValue setter_in)
109+ : parent_t (std::move(par)), setter(setter_in)
110+ {}
111+
112+ SetDefaultValue setter;
113+ void set (DefaultValue &&val) override
114+ {
115+ std::cout << " USING CUSTOM SETTER" << std::endl;
116+ (this ->child .*setter)(std::forward<DefaultValue>(val));
117+ }
118+ };
119+
30120template <typename Child> // CRT
31121class ScientificDefaults
32122{
@@ -37,6 +127,17 @@ class ScientificDefaults
37127 template <typename F>
38128 using setter_t = Child &(Child::*)();
39129
130+ template <typename GetDefaultValue>
131+ auto
132+ defaultAttribute (char const *attrName, GetDefaultValue &&getDefaultValue)
133+ -> ConfigAttribute<Child, GetDefaultValue>
134+ {
135+ return ConfigAttribute{
136+ asChild (),
137+ attrName,
138+ std::forward<GetDefaultValue>(getDefaultValue)};
139+ }
140+
40141 template <typename Setter = void , typename V>
41142 void addDefaultFor_worker (char const *key, V &&value, Setter &&setter);
42143
0 commit comments