Skip to content

Commit f862c18

Browse files
committed
Try further reducing amount of lambdas...
1 parent 1029198 commit f862c18

2 files changed

Lines changed: 222 additions & 163 deletions

File tree

include/openPMD/backend/ScientificDefaults_internal.hpp

Lines changed: 97 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,107 @@ namespace attribute_read_result
5050
{};
5151
} // namespace attribute_read_result
5252

53+
struct ProcessAttribute
54+
{
55+
virtual auto operator()(Attributable &, char const *, Attribute const &)
56+
-> std::optional<error::ReadError> = 0;
57+
virtual ~ProcessAttribute() = default;
58+
};
59+
60+
template <typename T>
61+
struct PostProcessConvertedAttribute
62+
{
63+
virtual auto operator()(T val) -> std::optional<error::ReadError> = 0;
64+
virtual ~PostProcessConvertedAttribute() = default;
65+
};
66+
67+
struct constructor_tag
68+
{};
69+
static constexpr constructor_tag constructor_tag_v = {};
70+
71+
template <typename T, typename Functor>
72+
struct PostProcessConvertedAttributeImpl : PostProcessConvertedAttribute<T>
73+
{
74+
template <typename T_, typename Functor_>
75+
friend auto makePostProcessConvertedAttribute(Functor_ &&fun)
76+
-> std::shared_ptr<PostProcessConvertedAttribute<T_>>;
77+
78+
template <typename Fun>
79+
PostProcessConvertedAttributeImpl(constructor_tag, Fun &&f)
80+
: fun{std::forward<Fun>(f)}
81+
{}
82+
83+
Functor fun;
84+
auto operator()(T val) -> std::optional<error::ReadError> override
85+
{
86+
return fun(std::move(val));
87+
}
88+
};
89+
90+
template <typename T, typename Fun>
91+
auto makePostProcessConvertedAttribute(Fun &&fun)
92+
-> std::shared_ptr<PostProcessConvertedAttribute<T>>
93+
{
94+
auto functor = [fun_lambda = std::forward<Fun>(fun)](
95+
T val) -> std::optional<error::ReadError> {
96+
if constexpr (!std::is_void_v<std::invoke_result<Fun &&, T>>)
97+
{
98+
std::move(fun_lambda)(std::move(val));
99+
return std::nullopt;
100+
}
101+
else
102+
{
103+
return std::move(fun_lambda)(std::move(val));
104+
}
105+
};
106+
return std::make_shared<
107+
PostProcessConvertedAttributeImpl<T, decltype(functor)>>(
108+
constructor_tag_v, std::move(functor));
109+
}
110+
111+
template <typename T>
112+
struct RequireType : ProcessAttribute
113+
{
114+
std::optional<std::shared_ptr<PostProcessConvertedAttribute<T>>>
115+
postProcess;
116+
117+
explicit RequireType() = default;
118+
119+
template <typename Functor>
120+
RequireType(constructor_tag, Functor &&fun)
121+
: postProcess(
122+
makePostProcessConvertedAttribute<T>(std::forward<Functor>(fun)))
123+
{}
124+
125+
auto operator()(Attributable &, char const *, Attribute const &)
126+
-> std::optional<error::ReadError> override;
127+
};
128+
129+
struct RequireVector : ProcessAttribute
130+
{
131+
auto operator()(Attributable &, char const *, Attribute const &)
132+
-> std::optional<error::ReadError> override;
133+
};
134+
135+
struct RequireScalar : ProcessAttribute
136+
{
137+
auto operator()(Attributable &, char const *, Attribute const &)
138+
-> std::optional<error::ReadError> override;
139+
};
140+
53141
using AttributeReadResult = std::variant<
54142
attribute_read_result::Success,
55143
attribute_read_result::TypeUnmatched,
56144
error::ReadError>;
57145

58146
struct AttributeReader
59147
{
60-
using process_attribute_type =
61-
std::function<std::optional<error::ReadError>(
62-
Attributable &, char const *, Attribute const &)>;
63-
64148
std::deque<Datatype> eligibleDatatypes;
65-
std::optional<process_attribute_type> processAttribute;
149+
std::optional<std::shared_ptr<ProcessAttribute>> processAttribute;
66150

67151
AttributeReader(
68152
std::deque<Datatype> eligibleDatatypes_in,
69-
std::optional<process_attribute_type> processAttribute_in);
153+
std::optional<std::shared_ptr<ProcessAttribute>> processAttribute_in);
70154

71155
auto operator()(
72156
Attributable &record,
@@ -95,7 +179,6 @@ struct ConfigAttribute
95179

96180
template <typename RecordType, typename ValueType>
97181
using set_default_val_t = RecordType &(RecordType::*)(ValueType);
98-
using process_attribute_type = AttributeReader::process_attribute_type;
99182

100183
ConfigAttribute(Attributable &child_in, char const *attrName_in);
101184

@@ -121,8 +204,8 @@ struct ConfigAttribute
121204

122205
[[nodiscard]] auto withReader(
123206
std::deque<Datatype> eligibleDatatypes,
124-
std::optional<process_attribute_type> processAttribute = std::nullopt)
125-
-> ConfigAttribute &;
207+
std::optional<std::shared_ptr<ProcessAttribute>> processAttribute =
208+
std::nullopt) -> ConfigAttribute &;
126209

127210
void write();
128211
void read();
@@ -133,18 +216,14 @@ struct ConfigAttribute
133216
// attributes in withReader()
134217
namespace
135218
{ // try converting to scalar values (e.g. when a vector of length 1 is given)
136-
extern ConfigAttribute::process_attribute_type require_scalar;
219+
extern std::shared_ptr<ProcessAttribute> require_scalar;
137220
// try converting to vectors (e.g. when a scalar or an array is given)
138-
extern ConfigAttribute::process_attribute_type require_vector;
139-
template <typename T>
140-
auto require_type(std::function<std::optional<error::ReadError>(T)>)
141-
-> ConfigAttribute::process_attribute_type;
142-
template <typename T>
143-
auto require_type_noerr(std::function<void(T)>)
144-
-> ConfigAttribute::process_attribute_type;
221+
extern std::shared_ptr<ProcessAttribute> require_vector;
222+
template <typename T, typename Fun>
223+
auto require_type(Fun &&) -> std::shared_ptr<ProcessAttribute>;
145224
// common case: directly use setAttribute
146225
template <typename T>
147-
auto require_type() -> ConfigAttribute::process_attribute_type;
226+
auto require_type() -> std::shared_ptr<ProcessAttribute>;
148227

149228
auto get_float_types() -> std::deque<Datatype>;
150229
auto get_string_types() -> std::deque<Datatype>;

0 commit comments

Comments
 (0)