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()
|
int main()
|
||||||
{
|
{
|
||||||
|
std::string id1 = "1", id2 = "2";
|
||||||
|
|
||||||
int i = 10;
|
int i = 10;
|
||||||
double d = 8.1;
|
double d = 8.1;
|
||||||
std::string s{"dwedjkwlk"};
|
std::string s{"dwedjkwlk"};
|
||||||
|
|
||||||
AdcGenericDevice<> dev("DEV#1");
|
AdcGenericDevice<> dev("DEV#1");
|
||||||
|
|
||||||
|
std::println("add RW-attr with id='{}' (val={})", id1, i);
|
||||||
dev.addAttr(
|
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](int ii) -> adc_error_t {
|
||||||
i = ii;
|
i = ii;
|
||||||
return AdcDeviceErrorCode::ERROR_OK;
|
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) {
|
if (ri) {
|
||||||
std::println("dev[1] = {}", ri.value());
|
std::println("dev[{}] = {}", id1, ri.value());
|
||||||
} else {
|
} 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) {
|
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) {
|
if (rd) {
|
||||||
std::println("dev[1] = {}", rd.value());
|
std::println("dev[{}] = {}", id1, rd.value());
|
||||||
} else {
|
} 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"];
|
double dd = 33.333;
|
||||||
if (ri) {
|
std::print("set '{}'-attr value to {} as double:\t", id1, dd);
|
||||||
std::println("dev[1] = {}", ri.value());
|
err = dev[id1] = dd;
|
||||||
} else {
|
|
||||||
std::println("cannot get dev[1] as int: {}", ri.error().message());
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dev["2"] = 0.29817;
|
|
||||||
if (err) {
|
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;
|
return 0;
|
||||||
|
|||||||
@@ -133,8 +133,49 @@ class AdcGenericDevice
|
|||||||
protected:
|
protected:
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
struct attr_t {
|
struct attr_t {
|
||||||
std::function<adc_result_t<VT>()> getter;
|
std::function<adc_result_t<VT>()> getter{};
|
||||||
std::function<adc_error_t(VT const&)> setter;
|
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,
|
adc_error_t serialize(snplib::snplib_output_char_range_c auto& output,
|
||||||
snplib::snplib_serialization_params_c auto const& params)
|
snplib::snplib_serialization_params_c auto const& params)
|
||||||
@@ -200,7 +241,7 @@ protected:
|
|||||||
template <typename VT>
|
template <typename VT>
|
||||||
adc_error_t operator=(VT&& val)
|
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) {
|
||||||
if (attr.value().setter) {
|
if (attr.value().setter) {
|
||||||
return attr.value().setter(std::forward<VT>(val));
|
return attr.value().setter(std::forward<VT>(val));
|
||||||
@@ -228,6 +269,22 @@ protected:
|
|||||||
snplib::HeterogenMap<ATTR_ID_T> _attrs{};
|
snplib::HeterogenMap<ATTR_ID_T> _attrs{};
|
||||||
|
|
||||||
public:
|
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 DEV_ID_T device_id_t;
|
||||||
typedef ATTR_ID_T attr_id_t;
|
typedef ATTR_ID_T attr_id_t;
|
||||||
typedef CMD_ID_T cmd_id_t;
|
typedef CMD_ID_T cmd_id_t;
|
||||||
@@ -255,9 +312,8 @@ public:
|
|||||||
_commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
_commands.emplace(std::move(id), std::forward<ET>(exec_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
// template <typename GT, typename ST, typename... VTs>
|
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, std::tuple<VTs...> = std::tuple<>{})
|
||||||
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
|
|
||||||
{
|
{
|
||||||
using v_t = snplib_attr_value_deduced_t<GT, ST>;
|
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!");
|
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!");
|
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)
|
adc_error_t operator()(CMD_ID_T id)
|
||||||
|
|||||||
Reference in New Issue
Block a user