add ability of authomatic attribute-value type conversion (for user

given types!)
This commit is contained in:
2026-07-15 15:52:10 +03:00
parent 6e1ef26aa6
commit bdaaaab559
2 changed files with 105 additions and 27 deletions

View File

@@ -133,8 +133,49 @@ class AdcGenericDevice
protected:
template <typename VT>
struct attr_t {
std::function<adc_result_t<VT>()> getter;
std::function<adc_error_t(VT const&)> setter;
std::function<adc_result_t<VT>()> getter{};
std::function<adc_error_t(VT const&)> setter{};
template <typename UT>
requires(requires(VT v, UT u) { v = u; } && !std::same_as<VT, UT>)
attr_t& operator=(attr_t<UT> const& other)
{
if (other.getter) {
getter = [&other]() -> adc_result_t<VT> {
auto val = other.getter();
if (val) {
return static_cast<VT>(val.value());
}
return std::unexpected(val.error());
};
} else { // write-only attribute
getter = nullptr;
}
if (other.setter) {
setter = [&other](VT const& v) { return other.setter(static_cast<UT>(v)); };
} else { // read-only attribute
setter = nullptr;
}
return *this;
}
template <typename UT>
requires requires(VT v, UT u) { v = u; }
operator attr_t<UT>() const
{
return attr_t<UT>{.getter = [this]() -> adc_result_t<UT> {
auto val = getter();
if (val) {
return static_cast<UT>(val.value());
} else {
return std::unexpected(val.error());
}
},
.setter = [this](UT const& u) { return setter(static_cast<VT>(u)); }};
}
adc_error_t serialize(snplib::snplib_output_char_range_c auto& output,
snplib::snplib_serialization_params_c auto const& params)
@@ -200,7 +241,7 @@ protected:
template <typename VT>
adc_error_t operator=(VT&& val)
{
auto attr = _dev._attrs.template get<attr_t<std::decay_t<VT>>>(_id);
auto attr = _dev._attrs.template get<attr_t<std::remove_cvref_t<VT>>>(_id);
if (attr) {
if (attr.value().setter) {
return attr.value().setter(std::forward<VT>(val));
@@ -228,6 +269,22 @@ protected:
snplib::HeterogenMap<ATTR_ID_T> _attrs{};
public:
static constexpr std::tuple<bool,
char,
short,
int,
long,
long long,
unsigned char,
unsigned short,
unsigned int,
unsigned long,
unsigned long long,
float,
double,
long double>
arithmetic_t{};
typedef DEV_ID_T device_id_t;
typedef ATTR_ID_T attr_id_t;
typedef CMD_ID_T cmd_id_t;
@@ -255,9 +312,8 @@ public:
_commands.emplace(std::move(id), std::forward<ET>(exec_func));
}
// template <typename GT, typename ST, typename... VTs>
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
template <typename GT, typename ST, typename... VTs>
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple<VTs...> = std::tuple<>{})
{
using v_t = snplib_attr_value_deduced_t<GT, ST>;
static_assert(!std::is_void_v<v_t>, "Getter and setter cannot be nullptr_t at the same time!");
@@ -266,7 +322,8 @@ public:
static_assert(std::invocable<ST, v_t const&>, "Invalid setter argument type!");
}
_attrs.push(std::move(id), attr_t<v_t>{.getter = std::forward<GT>(getter), .setter = std::forward<ST>(setter)});
_attrs.push(std::move(id), attr_t<v_t>{.getter = std::forward<GT>(getter), .setter = std::forward<ST>(setter)},
std::tuple<attr_t<VTs>...>{});
}
adc_error_t operator()(CMD_ID_T id)