This commit is contained in:
2026-07-01 18:32:45 +03:00
parent d198ddd08f
commit 4c500c0308
3 changed files with 36 additions and 69 deletions

View File

@@ -102,37 +102,33 @@ inline std::error_code make_error_code(AdcDeviceErrorCode ec)
}
namespace details
{
template <typename T>
concept snplib_getter_c = std::same_as<T, std::nullptr_t> || requires(T t) {
concept adclib_attr_getter_c = std::same_as<T, std::nullptr_t> || requires(T t) {
{ t() } -> adc_result_c;
};
template <typename T>
concept snplib_setter_c =
concept adclib_attr_setter_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_error_t, typename snplib::snplib_func_traits_t<T>::ret_t>);
// deduce value type from getter and setter
template <snplib_getter_c GT, snplib_setter_c ST>
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
using snplib_attr_value_deduced_t =
std::conditional_t<std::is_null_pointer_v<GT>,
std::conditional_t<std::is_null_pointer_v<ST>, void, snplib::snplib_func_arg1_t<ST>>,
typename std::invoke_result_t<GT>::value_type>;
} // namespace details
template <std::formattable<char> ATTR_ID_T = std::string_view, std::formattable<char> CMD_ID_T = std::string_view>
template <std::formattable<char> DEV_ID_T = std::string,
std::formattable<char> ATTR_ID_T = std::string,
std::formattable<char> CMD_ID_T = std::string>
class AdcGenericDevice
{
protected:
template <typename VT>
struct attr_t {
ATTR_ID_T id;
std::function<adc_result_t<VT>()> getter;
std::function<adc_error_t(VT const&)> setter;
@@ -178,9 +174,9 @@ protected:
attr_proxy_t(AdcGenericDevice& dev, ATTR_ID_T id) : _dev(dev), _id(std::move(id)) {}
template <typename VT>
operator adc_result_t<VT>()
operator adc_result_t<VT>() const
{
auto const& attr = _dev._attrs.template get<attr_t<VT>>(_id);
auto attr = _dev._attrs.template get<attr_t<VT>>(_id);
if (attr) {
if (attr.value().getter) {
return attr.value().getter();
@@ -200,7 +196,7 @@ protected:
template <typename VT>
adc_error_t operator=(VT&& val)
{
auto const& attr = _dev._attrs.template get<attr_t<VT>>(_id);
auto attr = _dev._attrs.template get<attr_t<VT>>(_id);
if (attr) {
if (attr.value().setter) {
return attr.value().setter(std::forward<VT>(val));
@@ -221,16 +217,26 @@ protected:
ATTR_ID_T _id;
};
DEV_ID_T _devId;
std::unordered_map<CMD_ID_T, std::function<void()>> _commands{};
snplib::HeterogenMap<ATTR_ID_T> _attrs{};
public:
typedef DEV_ID_T device_id_t;
typedef ATTR_ID_T attr_id_t;
typedef CMD_ID_T cmd_id_t;
enum AttrAccessType { ATTR_ACCESS_RW, ATTR_ACCESS_RO, ATTR_ACCESS_WO };
AdcGenericDevice() {}
AdcGenericDevice(device_id_t id) : _devId(id) {}
virtual ~AdcGenericDevice() = default;
device_id_t id() const
{
return _devId;
}
template <snplib::snplib_callable_c ET>
void addCommand(CMD_ID_T id, ET&& exec_func)
@@ -239,24 +245,10 @@ public:
}
// template <typename GT, typename ST, typename... VTs>
template <details::snplib_getter_c GT, details::snplib_setter_c ST, typename... VTs>
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter, std::tuple<VTs...> = std::tuple())
template <adclib_attr_getter_c GT, adclib_attr_setter_c ST>
void addAttr(ATTR_ID_T id, GT&& getter, ST&& setter)
{
// static_assert(!(std::is_null_pointer_v<GT> && std::is_null_pointer_v<ST>),
// "Getter and setter cannot be nullptr_t at the same time!");
// // deduce attribute value type
// using ret_t = std::invoke_result_t<GT>;
// static_assert(adc_result_c<ret_t>, "Invalid return type of the getter!");
// using v_t = typename ret_t::value_type;
// static_assert(std::invocable<ST, v_t const&>, "Invalid setter type!");
// static_assert(std::convertible_to<std::invoke_result_t<ST, v_t const&>, adc_error_t>,
// "Invalid return type of the setter!");
using v_t = details::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!");
if constexpr (!std::is_null_pointer_v<GT> && !std::is_null_pointer_v<ST>) {
@@ -264,34 +256,6 @@ public:
}
_attrs.push(std::move(id), attr_t<v_t>{.getter = std::forward<GT>(getter), .setter = std::forward<ST>(setter)});
// if constexpr (sizeof...(VTs)) {
// auto func = [id, this]<size_t I>() {
// using u_t = std::tuple_element_t<I, std::tuple<VTs...>>;
// if constexpr (!requires(u_t u, v_t v) {
// u = v;
// v = u;
// }) {
// static_assert(false, "Invalid user type!");
// }
// if constexpr (!std::same_as<u_t, v_t>) {
// _attrs.push(std::move(id), attr_t<u_t>{.getter = [id, this]() -> adc_result_t<u_t> {
// auto const& attr = _attrs.template
// get<attr_t<v_t>>(id); if (attr) {
// adc_result_t v = attr.getter();
// if (v) {
// return
// adc_result_t(static_cast<u_t>(v.value()));
// }
// }
// return AdcDeviceErrorCode::ERROR_UNKNOWN;
// },
// .setter = []() {}});
// }
// };
// }
}
adc_error_t operator()(CMD_ID_T id)