diff --git a/include/adclib/adclib_device1.h b/include/adclib/adclib_device1.h index c330485..9a4aaba 100644 --- a/include/adclib/adclib_device1.h +++ b/include/adclib/adclib_device1.h @@ -347,7 +347,7 @@ public: using tp_t = std::tuple; - [&id, getter_cap = std::forward(getter), setter_cap = std::forward(setter), + [id = std::move(id), getter_cap = std::forward(getter), setter_cap = std::forward(setter), this](std::index_sequence) mutable { return std::apply( [this](auto&&... args) { addAttr(std::forward(args)...); }, @@ -374,6 +374,115 @@ 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!"); + + [id = std::move(id), getter_cap = std::forward(getter), setter_cap = std::forward(setter), + tp = std::forward_as_tuple(std::forward(cnv_pairs)...), + this](std::index_sequence) mutable { + // + auto gt_cnv_from_func = [tp]() { + using tp_t = decltype(tp); + + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; + + using u_t = adclib_attr_user_deduced_t; + + return [tp = std::move(tp)](attr_getter_t const& gt) -> adc_result_t> { + return [tp = std::move(tp), >]() -> 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(tp))(v.value()); + } + + return std::unexpected(v.error()); + }; + }; + }; + + auto st_cnv_from_func = [tp]() { + using tp_t = decltype(tp); + + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; + + using u_t = adclib_attr_user_deduced_t; + + return [tp = std::move(tp)](attr_setter_t const& st) -> adc_result_t> { + return [tp = std::move(tp), &st](u_t const& uval) -> adc_error_t { + // convert from user type to inner ("convert-to" function)! + auto val = std::forward>(std::get(tp))(uval); + if (val) { + return st(val.value()); + } + + return val.error(); + }; + }; + }; + + auto gt_cnv_to_func = [tp]() { + using tp_t = decltype(tp); + + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; + + using u_t = adclib_attr_user_deduced_t; + + return [tp = std::move(tp)](attr_getter_t const& gt) -> adc_result_t> { + return [tp = std::move(tp), >]() -> adc_result_t { + auto uv = gt(); + if (uv) { + // convert to inner type from user's ("convert-to" function) + // it returns adc_result_t + return std::forward>(std::get(tp))(uv.value()); + } + + return std::unexpected(uv.error()); + }; + }; + }; + + auto st_cnv_to_func = [tp]() { + using tp_t = decltype(tp); + + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; + + using u_t = adclib_attr_user_deduced_t; + + return [tp = std::move(tp)](attr_setter_t const& st) -> adc_result_t> { + return [tp = std::move(tp), &st](v_t const& val) -> adc_error_t { + // convert to user type from inner ("convert-from" function)! + auto uval = std::forward>(std::get(tp))(val); + if (uval) { + return st(uval.value()); + } + + return uval.error(); + }; + }; + }; + + std::apply( + [this](auto&&... args) { _attrGetter.push(std::forward(args)...); }, + std::tuple_cat( + std::forward_as_tuple(id, attr_getter_t(std::forward(getter_cap))), + std::tuple_cat(std::forward_as_tuple(gt_cnv_from_func.template operator()<2 * Is>(), + gt_cnv_to_func.template operator()<2 * Is>())...))); + + std::apply( + [this](auto&&... args) { _attrSetter.push(std::forward(args)...); }, + std::tuple_cat( + std::forward_as_tuple(id, attr_setter_t(std::forward(setter_cap))), + std::tuple_cat(std::forward_as_tuple(st_cnv_from_func.template operator()<2 * Is>(), + st_cnv_to_func.template operator()<2 * Is>())...))); + }(std::make_index_sequence>{}); + + return; + + [... 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)...);