...
This commit is contained in:
@@ -6,7 +6,7 @@ using namespace adc;
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::string id1 = "1", id2 = "2";
|
std::string id1 = "1", id2 = "2", id3 = "str";
|
||||||
|
|
||||||
int i = 10;
|
int i = 10;
|
||||||
double d = 8.1;
|
double d = 8.1;
|
||||||
@@ -32,6 +32,19 @@ int main()
|
|||||||
std::println("add RO-attr with id='{}' (val={})", id2, d);
|
std::println("add RO-attr with id='{}' (val={})", id2, d);
|
||||||
dev.addAttr(id2, [&d]() -> adc_result_t<double> { return d; }, nullptr);
|
dev.addAttr(id2, [&d]() -> adc_result_t<double> { return d; }, nullptr);
|
||||||
|
|
||||||
|
std::println("add RW-attr with id='{}' (val={})", id3, s);
|
||||||
|
dev.addAttr(
|
||||||
|
id3, [&s]() -> adc_result_t<std::string> { return s; },
|
||||||
|
[&s](std::string const& sv) -> adc_error_t {
|
||||||
|
s = sv;
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
[&s](adc_result_t<std::string> const&) -> adc_result_t<const char*> { return s.c_str(); },
|
||||||
|
[&s](adc_result_t<const char*> const& p) -> adc_result_t<std::string> {
|
||||||
|
s = p.value();
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
|
||||||
std::print("get '{}'-attr value as native int:\t", id1);
|
std::print("get '{}'-attr value as native int:\t", id1);
|
||||||
adc_result_t<int> ri = dev[id1];
|
adc_result_t<int> ri = dev[id1];
|
||||||
if (ri) {
|
if (ri) {
|
||||||
|
|||||||
@@ -119,10 +119,38 @@ concept adclib_attr_setter_c =
|
|||||||
|
|
||||||
// deduce value type from getter and setter
|
// deduce value type from getter and setter
|
||||||
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
||||||
using snplib_attr_value_deduced_t =
|
using adclib_attr_value_deduced_t = std::conditional_t<
|
||||||
std::conditional_t<std::is_null_pointer_v<GT>,
|
std::is_null_pointer_v<GT>,
|
||||||
std::conditional_t<std::is_null_pointer_v<ST>, void, snplib::snplib_func_arg1_t<ST>>,
|
std::conditional_t<std::is_null_pointer_v<ST>, void, std::remove_cvref_t<snplib::snplib_func_arg1_t<ST>>>,
|
||||||
typename std::invoke_result_t<GT>::value_type>;
|
typename std::invoke_result_t<GT>::value_type>;
|
||||||
|
|
||||||
|
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
|
||||||
|
struct adclib_is_deduced_void_t {
|
||||||
|
static constexpr bool value = std::is_void_v<adclib_attr_value_deduced_t<GT, ST>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// conversional function signature:
|
||||||
|
// "from": adc_result_t<UT> func(const adc_result_t<VT>&)
|
||||||
|
// "to": adc_result_t<VT> func(const adc_result_t<UT>&)
|
||||||
|
template <typename T, typename VT>
|
||||||
|
concept adclib_attr_conv_from_func_c =
|
||||||
|
std::same_as<T, std::nullptr_t> ||
|
||||||
|
(std::invocable<T, const adc_result_t<VT>&> && !std::is_void_v<std::invoke_result_t<T, const adc_result_t<VT>&>>);
|
||||||
|
|
||||||
|
template <typename T, typename VT>
|
||||||
|
concept adclib_attr_conv_to_func_c = std::same_as<T, std::nullptr_t> ||
|
||||||
|
(snplib::snplib_callable_c<T> && (snplib::snplib_func_traits_t<T>::arity == 1) &&
|
||||||
|
std::same_as<adc_result_t<VT>, typename snplib::snplib_func_traits_t<T>::ret_t>);
|
||||||
|
|
||||||
|
template <typename VT, adclib_attr_conv_from_func_c<VT> CONV_FROM_T, adclib_attr_conv_to_func_c<VT> CONV_TO_T>
|
||||||
|
using adclib_attr_user_deduced_t =
|
||||||
|
std::conditional_t<std::is_null_pointer_v<CONV_FROM_T>,
|
||||||
|
std::conditional_t<std::is_null_pointer_v<CONV_TO_T>,
|
||||||
|
void,
|
||||||
|
std::remove_cvref_t<snplib::snplib_func_arg1_t<CONV_TO_T>>>,
|
||||||
|
typename snplib::snplib_func_traits_t<CONV_FROM_T>::ret_t>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <std::formattable<char> DEV_ID_T = std::string,
|
template <std::formattable<char> DEV_ID_T = std::string,
|
||||||
@@ -136,31 +164,32 @@ protected:
|
|||||||
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>
|
// template <typename UT>
|
||||||
requires(requires(VT v, UT u) { v = u; } && !std::same_as<VT, UT>)
|
// requires(requires(VT v, UT u) { v = u; } && !std::same_as<VT, UT>)
|
||||||
attr_t& operator=(attr_t<UT> const& other)
|
// attr_t& operator=(attr_t<UT> const& other)
|
||||||
{
|
// {
|
||||||
if (other.getter) {
|
// std::println("ATTR::operator=");
|
||||||
getter = [&other]() -> adc_result_t<VT> {
|
// if (other.getter) {
|
||||||
auto val = other.getter();
|
// getter = [&other]() -> adc_result_t<VT> {
|
||||||
if (val) {
|
// auto val = other.getter();
|
||||||
return static_cast<VT>(val.value());
|
// if (val) {
|
||||||
}
|
// return static_cast<VT>(val.value());
|
||||||
|
// }
|
||||||
|
|
||||||
return std::unexpected(val.error());
|
// return std::unexpected(val.error());
|
||||||
};
|
// };
|
||||||
} else { // write-only attribute
|
// } else { // write-only attribute
|
||||||
getter = nullptr;
|
// getter = nullptr;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (other.setter) {
|
// if (other.setter) {
|
||||||
setter = [&other](VT const& v) { return other.setter(static_cast<UT>(v)); };
|
// setter = [&other](VT const& v) { return other.setter(static_cast<UT>(v)); };
|
||||||
} else { // read-only attribute
|
// } else { // read-only attribute
|
||||||
setter = nullptr;
|
// setter = nullptr;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return *this;
|
// return *this;
|
||||||
}
|
// }
|
||||||
|
|
||||||
template <typename UT>
|
template <typename UT>
|
||||||
requires requires(VT v, UT u) { v = u; }
|
requires requires(VT v, UT u) { v = u; }
|
||||||
@@ -315,7 +344,7 @@ public:
|
|||||||
template <typename GT, typename ST, typename... VTs>
|
template <typename GT, typename ST, typename... VTs>
|
||||||
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, std::tuple<VTs...> = std::tuple<>{})
|
||||||
{
|
{
|
||||||
using v_t = snplib_attr_value_deduced_t<GT, ST>;
|
using v_t = adclib_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!");
|
||||||
|
|
||||||
if constexpr (!std::is_null_pointer_v<GT> && !std::is_null_pointer_v<ST>) {
|
if constexpr (!std::is_null_pointer_v<GT> && !std::is_null_pointer_v<ST>) {
|
||||||
@@ -326,9 +355,79 @@ public:
|
|||||||
std::tuple<attr_t<VTs>...>{});
|
std::tuple<attr_t<VTs>...>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST, typename... FuncTs>
|
||||||
|
requires(sizeof...(FuncTs) > 1)
|
||||||
|
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, FuncTs&&... cnv_pairs)
|
||||||
|
{
|
||||||
|
static constexpr size_t NFUNCS = sizeof...(FuncTs);
|
||||||
|
|
||||||
|
static_assert(NFUNCS % 2 == 0, "Number of conversional functions must be an even!");
|
||||||
|
|
||||||
|
using v_t = adclib_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!");
|
||||||
|
|
||||||
|
auto from_cnv_func = [](adclib_attr_conv_from_func_c<v_t> auto&& conv_from,
|
||||||
|
adclib_attr_conv_to_func_c<v_t> auto&& conv_to) {
|
||||||
|
using u_t = adclib_attr_user_deduced_t<v_t, decltype(conv_from), decltype(conv_to)>;
|
||||||
|
|
||||||
|
return [conv_from_cap = std::forward<decltype(conv_from)>(conv_from),
|
||||||
|
conv_to_cap =
|
||||||
|
std::forward<decltype(conv_to)>(conv_to)](attr_t<v_t> const& attr) mutable -> attr_t<u_t> {
|
||||||
|
return attr_t<u_t>{.getter = [&attr, conv_from_cap_cap = std::forward<decltype(conv_from_cap)>(
|
||||||
|
conv_from_cap)]() mutable -> adc_result_t<u_t> {
|
||||||
|
return conv_from_cap_cap(attr.getter());
|
||||||
|
},
|
||||||
|
.setter = [&attr, conv_to_cap_cap = std::forward<decltype(conv_to_cap)>(
|
||||||
|
conv_to_cap)](u_t const& uv) mutable -> adc_error_t {
|
||||||
|
auto val = conv_to_cap_cap(uv);
|
||||||
|
if (val) {
|
||||||
|
return attr.setter(val.value());
|
||||||
|
} else {
|
||||||
|
return std::unexpected(val.error());
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto to_cnv_func = [id, this](adclib_attr_conv_from_func_c<v_t> auto&& conv_from,
|
||||||
|
adclib_attr_conv_to_func_c<v_t> auto&& conv_to) {
|
||||||
|
using u_t = adclib_attr_user_deduced_t<v_t, decltype(conv_from), decltype(conv_to)>;
|
||||||
|
|
||||||
|
return [id, this](attr_t<u_t> const&) -> attr_t<v_t> { return _attrs.template get<attr_t<v_t>>(id); };
|
||||||
|
};
|
||||||
|
|
||||||
|
std::apply([this](auto&&... args) { _attrs.pushWithCnv(std::forward<decltype(args)>(args)...); },
|
||||||
|
std::tuple_cat(std::forward_as_tuple(id, getter, setter),
|
||||||
|
[... cnv_pairs_cap = std::forward<FuncTs>(cnv_pairs), from_cnv_func, to_cnv_func, id,
|
||||||
|
this]<size_t... Is>(std::index_sequence<Is...>) mutable {
|
||||||
|
auto&& tp = std::forward_as_tuple(std::forward<FuncTs>(cnv_pairs_cap)...);
|
||||||
|
|
||||||
|
// static_assert(
|
||||||
|
// std::disjunction_v<adclib_is_deduced_void_t<std::tuple_element_t<Is * 2,
|
||||||
|
// decltype(tp)>,
|
||||||
|
// std::tuple_element_t<Is * 2 +
|
||||||
|
// 1, decltype(tp)>>...>,
|
||||||
|
// "Getter and setter cannot be nullptr_t at the same time!");
|
||||||
|
|
||||||
|
// return std::forward_as_tuple(
|
||||||
|
// [](attr_t<v_t> const& av)
|
||||||
|
// -> adclib_attr_value_deduced_t<std::tuple_element_t<Is * 2,
|
||||||
|
// decltype(tp)>,
|
||||||
|
// std::tuple_element_t<Is * 2 + 1,
|
||||||
|
// decltype(tp)>>
|
||||||
|
// {}...);
|
||||||
|
|
||||||
|
return std::forward_as_tuple(
|
||||||
|
from_cnv_func(std::get<Is * 2>(tp), std::get<Is * 2 + 1>(tp))...,
|
||||||
|
to_cnv_func(std::get<Is * 2>(tp), std::get<Is * 2 + 1>(tp))...);
|
||||||
|
// (from_cnv_func(std::get<Is * 2>(tp), std::get<Is * 2 + 1>(tp)),
|
||||||
|
// to_cnv_func(std::get<Is * 2>(tp), std::get<Is * 2 + 1>(tp)))...);
|
||||||
|
}(std::make_index_sequence<NFUNCS / 2>{})));
|
||||||
|
}
|
||||||
|
|
||||||
// add attribute of one of arithmetic type
|
// add attribute of one of arithmetic type
|
||||||
template <typename GT, typename ST>
|
template <typename GT, typename ST>
|
||||||
requires std::is_arithmetic_v<snplib_attr_value_deduced_t<GT, ST>>
|
requires std::is_arithmetic_v<adclib_attr_value_deduced_t<GT, ST>>
|
||||||
void addArithAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
|
void addArithAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
|
||||||
{
|
{
|
||||||
addAttr(std::move(id), std::forward<GT>(getter), std::forward<ST>(setter), AdcGenericDevice::arithmetic_types);
|
addAttr(std::move(id), std::forward<GT>(getter), std::forward<ST>(setter), AdcGenericDevice::arithmetic_types);
|
||||||
|
|||||||
Reference in New Issue
Block a user