diff --git a/include/adclib/adclib_device1.h b/include/adclib/adclib_device1.h index dd379b1..19496f8 100644 --- a/include/adclib/adclib_device1.h +++ b/include/adclib/adclib_device1.h @@ -226,6 +226,40 @@ protected: snplib::HeterogenMap _attrGetter{}; snplib::HeterogenMap _attrSetter{}; + + template + requires requires(std::invoke_result_t v, std::invoke_result_t u) { u = v; } + inline static auto default_cnv_from_func = [](GT const& g) -> adc_result_t { + using u_t = std::invoke_result_t; + + return [g]() -> adc_result_t { + auto v = g(); + + if (v) { + return static_cast(v.value()); + } + + return v.error(); + }; + }; + + + template + requires requires(std::invoke_result_t v, std::invoke_result_t u) { v = u; } + inline static auto default_cnv_to_func = [](UGT const& g) -> adc_result_t { + using v_t = std::invoke_result_t; + + return [g]() -> adc_result_t { + auto v = g(); + + if (v) { + return static_cast(v.value()); + } + + return v.error(); + }; + }; + public: static constexpr std::tuple(exec_func)); } - template - void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple = std::tuple<>{}) + template + void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple = std::tuple<>{}) { using v_t = adclib_attr_value_deduced_t; static_assert(!std::is_void_v, "Getter and setter cannot be nullptr_t at the same time!"); @@ -281,12 +315,15 @@ public: } _attrGetter.push(id, attr_getter_t>(std::forward(getter)), - std::tuple...>{}); + std::tuple...>{}); _attrSetter.push(id, attr_setter_t>(std::forward(setter)), - std::tuple...>{}); + std::tuple...>{}); } + // + // conversional functions are the same as defined in the snplib::hmap class + // (it must convert attribute values instead of getters or setters itself!) template requires(sizeof...(FuncTs) > 1) void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, FuncTs&&... cnv_pairs) @@ -297,6 +334,48 @@ public: using v_t = adclib_attr_value_deduced_t; static_assert(!std::is_void_v, "Getter and setter cannot be nullptr_t at the same time!"); + + [... cnv_pairs_cap = std::forward(cnv_pairs), id, getter_cap = std::forward(getter), + setter_cap = std::forward(setter), this](std::index_sequence) mutable { + auto tp = std::forward_as_tuple(std::forward(cnv_pairs_cap)...); + + auto gt_cnv_from_func = [](TpT const& tpl) { + using u_t = std::tuple_element_t::value_type; + + static_assert(requires(v_t v, u_t u) { u = v; }, "Invalid deduced user type!"); + + return [&tpl](attr_getter_t const& gt) -> adc_result_t> { + return [&tpl, >]() -> adc_result_t { + auto v = gt(); + if (v) { + // convert from inner type to user's ("convert-from" function) + // it returns adc_result_t + return std::forward>(std::get(tpl))(v.value()); + } + + return std::unexpected(v.error()); + }; + }; + }; + + auto st_cnv_from_func = [](TpT const& tpl) { + using u_t = std::tuple_element_t::value_type; + + static_assert(requires(v_t v, u_t u) { u = v; }, "Invalid deduced user type!"); + + return [&tpl](attr_setter_t const& st) -> adc_result_t> { + return [&tpl, &st](u_t const& uval) -> adc_error_t { + // convert from user type to inner ("convert-to" function)! + auto val = std::forward>(std::get(tpl))(uval); + if (val) { + return st(val.value()); + } + + return std::unexpected(val.error()); + }; + }; + }; + }(std::make_index_sequence{}); } };