add ability of authomatic attribute-value type conversion (for user
given types!)
This commit is contained in:
@@ -6,50 +6,71 @@ using namespace adc;
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string id1 = "1", id2 = "2";
|
||||
|
||||
int i = 10;
|
||||
double d = 8.1;
|
||||
std::string s{"dwedjkwlk"};
|
||||
|
||||
AdcGenericDevice<> dev("DEV#1");
|
||||
|
||||
std::println("add RW-attr with id='{}' (val={})", id1, i);
|
||||
dev.addAttr(
|
||||
"1", [&i]() -> adc_result_t<int> { return i; },
|
||||
id1, [&i]() -> adc_result_t<int> { return i; },
|
||||
[&i](int ii) -> adc_error_t {
|
||||
i = ii;
|
||||
return AdcDeviceErrorCode::ERROR_OK;
|
||||
});
|
||||
},
|
||||
std::tuple<double, int, long>{});
|
||||
|
||||
dev.addAttr("2", [&d]() -> adc_result_t<double> { return d; }, nullptr);
|
||||
std::println("add RO-attr with id='{}' (val={})", id2, d);
|
||||
dev.addAttr(id2, [&d]() -> adc_result_t<double> { return d; }, nullptr);
|
||||
|
||||
adc_result_t<int> ri = dev["1"];
|
||||
std::print("get '{}'-attr value as native int:\t", id1);
|
||||
adc_result_t<int> ri = dev[id1];
|
||||
if (ri) {
|
||||
std::println("dev[1] = {}", ri.value());
|
||||
std::println("dev[{}] = {}", id1, ri.value());
|
||||
} else {
|
||||
std::println("cannot get dev[1] as int: {}", ri.error().message());
|
||||
std::println("cannot get dev[{}] as int: {}", id1, ri.error().message());
|
||||
}
|
||||
|
||||
auto err = dev["1"] = 77;
|
||||
int ii = 77;
|
||||
std::print("set '{}'-attr value to {} as native int:\t", id1, ii);
|
||||
auto err = dev[id1] = ii;
|
||||
if (err) {
|
||||
std::println("cannot set dev[1] as int: {}", err.message());
|
||||
std::println("cannot set dev[{}] as int: {}", id1, err.message());
|
||||
} else {
|
||||
std::println("OK");
|
||||
}
|
||||
|
||||
adc_result_t<double> rd = dev["1"];
|
||||
std::print("get '{}'-attr value as double:\t", id1);
|
||||
adc_result_t<double> rd = dev[id1];
|
||||
if (rd) {
|
||||
std::println("dev[1] = {}", rd.value());
|
||||
std::println("dev[{}] = {}", id1, rd.value());
|
||||
} else {
|
||||
std::println("cannot get dev[1] as double: {}", rd.error().message());
|
||||
std::println("cannot get dev[{}] as double: {}", id1, rd.error().message());
|
||||
}
|
||||
|
||||
ri = dev["1"];
|
||||
if (ri) {
|
||||
std::println("dev[1] = {}", ri.value());
|
||||
} else {
|
||||
std::println("cannot get dev[1] as int: {}", ri.error().message());
|
||||
}
|
||||
|
||||
err = dev["2"] = 0.29817;
|
||||
double dd = 33.333;
|
||||
std::print("set '{}'-attr value to {} as double:\t", id1, dd);
|
||||
err = dev[id1] = dd;
|
||||
if (err) {
|
||||
std::println("cannot set dev[2] as double: {}", err.message());
|
||||
std::println("cannot set dev[{}] as double: {}", id1, err.message());
|
||||
} else {
|
||||
std::println("OK");
|
||||
}
|
||||
|
||||
std::print("get '{}'-attr value as native int:\t", id1);
|
||||
ri = dev[id1];
|
||||
if (ri) {
|
||||
std::println("dev[{}] = {}", id1, ri.value());
|
||||
} else {
|
||||
std::println("cannot get dev[{}] as int: {}", id1, ri.error().message());
|
||||
}
|
||||
|
||||
err = dev[id2] = 0.29817;
|
||||
if (err) {
|
||||
std::println("cannot set dev[{}] as double: {}", id2, err.message());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user