diff --git a/examples/device_exam.cpp b/examples/device_exam.cpp index ac4e169..ba32095 100644 --- a/examples/device_exam.cpp +++ b/examples/device_exam.cpp @@ -1,6 +1,6 @@ #include -#include +#include using namespace adc; @@ -39,12 +39,15 @@ int main() s = sv; return {}; }, - [&s](adc_result_t const&) -> adc_result_t { return s.c_str(); }, - [&s](adc_result_t const& p) mutable -> adc_result_t { - // s = p.value(); - // return s; - return std::string(p.value()); - }); + [](std::string const& v) -> adc_result_t { return v.c_str(); }, + [](const char* p) -> adc_result_t { return std::string(p); } + // [&s](adc_result_t const&) -> adc_result_t { return s.c_str(); }, + // [&s](adc_result_t const& p) mutable -> adc_result_t { + // // s = p.value(); + // // return s; + // return std::string(p.value()); + // } + ); std::print("get '{}'-attr value as native int:\t", id1); adc_result_t ri = dev[id1]; diff --git a/include/adclib/adclib_device1.h b/include/adclib/adclib_device1.h index 19496f8..b2fb5a7 100644 --- a/include/adclib/adclib_device1.h +++ b/include/adclib/adclib_device1.h @@ -132,12 +132,12 @@ struct adclib_is_deduced_void_t { }; // conversional function signature: -// "from": adc_result_t func(const adc_result_t&) -// "to": adc_result_t func(const adc_result_t&) +// "from": adc_result_t func(const VT&) +// "to": adc_result_t func(const UT&) template concept adclib_attr_conv_from_func_c = std::same_as || - (std::invocable&> && !std::is_void_v&>>); + (std::invocable && !std::is_void_v>); template concept adclib_attr_conv_to_func_c = std::same_as || @@ -150,7 +150,7 @@ using adclib_attr_user_deduced_t = std::conditional_t, void, std::remove_cvref_t>>, - typename snplib::snplib_func_traits_t::ret_t>; + typename snplib::snplib_func_traits_t::ret_t::value_type>; @@ -185,7 +185,7 @@ protected: } } - if (getter.error() == snplib::HeterogenMap::ERROR_NO_ELEM) { + if (getter.error() == snplib::hmap_error_e::ERROR_INVALID_KEY) { return std::unexpected(AdcDeviceErrorCode::ERROR_NO_ATTR_ID); } @@ -205,7 +205,7 @@ protected: } } - if (setter.error() == snplib::HeterogenMap::ERROR_NO_ELEM) { + if (setter.error() == snplib::hmap_error_e::ERROR_INVALID_KEY) { return AdcDeviceErrorCode::ERROR_NO_ATTR_ID; } @@ -223,8 +223,10 @@ protected: std::unordered_map> _commands{}; std::unordered_map _attrs{}; - snplib::HeterogenMap _attrGetter{}; - snplib::HeterogenMap _attrSetter{}; + // snplib::HeterogenMap _attrGetter{}; + // snplib::HeterogenMap _attrSetter{}; + snplib::hmap _attrGetter{}; + snplib::hmap _attrSetter{}; template @@ -314,11 +316,29 @@ public: static_assert(std::invocable, "Invalid setter argument type!"); } - _attrGetter.push(id, attr_getter_t>(std::forward(getter)), - std::tuple...>{}); + using tp_t = std::tuple; - _attrSetter.push(id, attr_setter_t>(std::forward(setter)), - std::tuple...>{}); + [&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)...); }, + std::tuple_cat( + std::forward_as_tuple(id, std::forward(getter_cap), + std::forward(setter_cap)), + std::tuple_cat(std::forward_as_tuple( + decltype(_attrGetter)::template trivial_conv_from>, + decltype(_attrGetter)::template trivial_conv_to>)...))); + }(std::make_index_sequence{}); + + // [&id, setter_cap = std::forward(setter), this](std::index_sequence) mutable { + // return std::apply( + // [this](auto&&... args) { addAttr(std::forward(args)...); }, + // std::tuple_cat( + // std::forward_as_tuple(id, std::forward(setter_cap)), + // std::tuple_cat(std::forward_as_tuple( + // decltype(_attrSetter)::template trivial_conv_from>, + // decltype(_attrSetter)::template trivial_conv_to>)...))); + // }(std::make_index_sequence{}); } // @@ -340,9 +360,13 @@ public: 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; + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; - static_assert(requires(v_t v, u_t u) { u = v; }, "Invalid deduced user type!"); + // using u_t = adclib_attr_user_deduced_t; + using u_t = std::invoke_result_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 { @@ -359,9 +383,12 @@ public: }; auto st_cnv_from_func = [](TpT const& tpl) { - using u_t = std::tuple_element_t::value_type; + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; - static_assert(requires(v_t v, u_t u) { u = v; }, "Invalid deduced user type!"); + using u_t = adclib_attr_user_deduced_t; + + // 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 { @@ -371,12 +398,105 @@ public: return st(val.value()); } - return std::unexpected(val.error()); + return val.error(); }; }; }; + + auto gt_cnv_to_func = [](TpT const& tpl) { + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; + + using u_t = adclib_attr_user_deduced_t; + + // static_assert(requires(v_t v, u_t u) { v = u; }, "Invalid deduced user type!"); + + return [&tpl](attr_getter_t const& gt) -> adc_result_t> { + return [&tpl, >]() -> 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(tpl))(uv.value()); + } + + return std::unexpected(uv.error()); + }; + }; + }; + + auto st_cnv_to_func = [](TpT const& tpl) { + using from_fn_t = std::decay_t>; + using to_fn_t = std::decay_t>; + + using u_t = adclib_attr_user_deduced_t; + + // static_assert(requires(v_t v, u_t u) { v = u; }, "Invalid deduced user type!"); + + return [&tpl](attr_setter_t const& st) -> adc_result_t> { + return [&tpl, &st](v_t const& val) -> adc_error_t { + // convert to user type from inner ("convert-from" function)! + auto uval = std::forward>(std::get(tpl))(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, std::forward(getter_cap)), + std::tuple_cat(std::forward_as_tuple(gt_cnv_from_func.template operator()(tp), + gt_cnv_to_func.template operator()(tp))...))); + + std::apply( + [this](auto&&... args) { _attrSetter.push(std::forward(args)...); }, + std::tuple_cat(std::forward_as_tuple(id, std::forward(setter_cap)), + std::tuple_cat(std::forward_as_tuple(st_cnv_from_func.template operator()(tp), + st_cnv_to_func.template operator()(tp))...))); }(std::make_index_sequence{}); } + + // add attribute of one of arithmetic type + template + requires std::is_arithmetic_v> + void addArithAttr(ATTR_ID_T id, GT&& getter, ST&& setter) + { + addAttr(std::move(id), std::forward(getter), std::forward(setter), AdcGenericDevice::arithmetic_types); + } + + adc_error_t operator()(CMD_ID_T id) + { + if (auto it = _commands.find(id); it != _commands.end()) { + // return (*it)(); + return it->second(); + } + + return AdcDeviceErrorCode::ERROR_NO_CMD_ID; + } + + + auto operator[](ATTR_ID_T id) + { + return attr_t{*this, std::move(id)}; + } + + + // function-like access to attributes + template + adc_result_t attr(ATTR_ID_T id) + { + return attr_t{*this, std::move(id)}; + } + + template + adc_error_t attr(ATTR_ID_T id, VT const& v) + { + return attr_t{*this, std::move(id)} = v; + } };