From fad61ea1dfcad9ed805a53b6e89ff289a6f2e4e6 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Sun, 24 Mar 2024 23:48:52 +0300 Subject: [PATCH] AdcValueHolder class: tests are passed --- common/adc_value_holder.h | 132 +++++++++++++++++++++++++++------ tests/adc_valueholder_test.cpp | 94 ++++++++++++++++------- 2 files changed, 178 insertions(+), 48 deletions(-) diff --git a/common/adc_value_holder.h b/common/adc_value_holder.h index 6bc1236..8c0c9c0 100644 --- a/common/adc_value_holder.h +++ b/common/adc_value_holder.h @@ -97,7 +97,6 @@ class AdcValueHolder { protected: template - // using arg_t = typename traits::adc_func_traits::ret_t; using arg_t = typename traits::adc_func_traits>::ret_t; std::function _getterWrapper; @@ -158,7 +157,21 @@ protected: public: // default trivial types (just arithmetic ones) - constexpr static std::tuple _defaultTrivialConvTypes{}; + constexpr static std::tuple + _defaultTrivialConvTypes{}; // always-true validator // constexpr static auto AdcValueHolderDummyValidator = [](const auto&) { return true; }; @@ -172,8 +185,7 @@ public: AdcValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter, - std::predicate&> auto&& validator = - AdcValueHolder::AdcValueHolderDummyValidator>) + std::predicate&> auto&& validator) : _internalTypeIndex(std::type_index(typeid(arg_t))) { init(std::forward(getter), std::forward(setter), @@ -181,12 +193,20 @@ public: } + // NOTE: due to using of concepts one cannot use of default value for validator callable!!! + AdcValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter) + : AdcValueHolder(std::forward(getter), + std::forward(setter), + AdcValueHolder::AdcValueHolderDummyValidator>) + { + } + + template AdcValueHolder(std::invocable<> auto&& getter, std::invocable&> auto&& setter, - const std::tuple& trivialConvTypes, - std::predicate&> auto&& validator = - AdcValueHolder::AdcValueHolderDummyValidator>) + std::predicate&> auto&& validator, + const std::tuple& /* tuple-of-trivially-converting-types */) : AdcValueHolder(std::forward(getter), std::forward(setter), std::forward(validator)) @@ -196,6 +216,18 @@ public: } + template + AdcValueHolder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter, + const std::tuple& t /* tuple-of-trivially-converting-types */) + : AdcValueHolder(std::forward(getter), + std::forward(setter), + AdcValueHolder::AdcValueHolderDummyValidator>, + t) + { + } + + AdcValueHolder(const AdcValueHolder&) = default; AdcValueHolder(AdcValueHolder&&) = default; @@ -215,10 +247,10 @@ public: } - AdcValueHolder& resetValueHolder( - std::invocable<> auto&& getter, - std::invocable&> auto&& setter, - std::predicate&> auto&& validator = AdcValueHolderDummyValidator) + AdcValueHolder& resetValueHolder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter, + std::predicate&> auto&& validator = + AdcValueHolder::AdcValueHolderDummyValidator>) { _convertFromInternal.clear(); _convertToInternal.clear(); @@ -230,12 +262,19 @@ public: } + AdcValueHolder& resetValueHolder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter) + { + return resetValueHolder(std::forward(getter), std::forward(setter), + AdcValueHolder::AdcValueHolderDummyValidator>); + } + + template - AdcValueHolder& resetValueHolder( - std::invocable<> auto&& getter, - std::invocable&> auto&& setter, - const std::tuple& trivialConvTypes, - std::predicate&> auto&& validator = AdcValueHolderDummyValidator) + AdcValueHolder& resetValueHolder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter, + std::predicate&> auto&& validator, + const std::tuple& /* tuple-of-trivially-converting-types */) { resetValueHolder(std::forward(getter), std::forward(setter), std::forward(validator)); @@ -247,11 +286,22 @@ public: } + template + AdcValueHolder& resetValueHolder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter, + const std::tuple& t /* tuple-of-trivially-converting-types */) + { + return resetValueHolder(std::forward(getter), std::forward(setter), + AdcValueHolder::AdcValueHolderDummyValidator>, + t); + } + + template AdcValueHolder& addConvertFunc(std::invocable auto&& func_to_internal, std::invocable auto&& func_from_internal) { - static_assert(std::is_same_v, "void IS NOT VALID TYPE!!!"); + static_assert(!std::is_same_v, "void IS NOT VALID TYPE!!!"); auto t_index = std::type_index(typeid(UT)); @@ -286,9 +336,13 @@ public: template operator UT() { + using v_t = std::remove_reference_t; + using val_t = std::conditional_t, std::add_pointer_t>, v_t>; + std::any val; - auto t_index = std::type_index(typeid(UT)); + // auto t_index = std::type_index(typeid(UT)); + auto t_index = std::type_index(typeid(val_t)); auto it = _convertFromInternal.find(t_index); if (it == _convertFromInternal.end()) { @@ -298,15 +352,21 @@ public: _getterWrapper(val); it->second(val); // call conversion function - return std::any_cast(val); + // return std::any_cast(val); + return std::any_cast(val); } template - AdcValueHolder& operator=(const UT& value) + AdcValueHolder& operator=(UT&& value) { - std::any val = std::make_any(value); + using v_t = std::remove_reference_t; + using val_t = std::conditional_t, std::add_pointer_t>, v_t>; - auto t_index = std::type_index(typeid(UT)); + // std::any val = std::make_any(value); + std::any val = std::make_any(value); + + // auto t_index = std::type_index(typeid(UT)); + auto t_index = std::type_index(typeid(val_t)); auto it = _convertToInternal.find(t_index); if (it == _convertToInternal.end()) { @@ -358,5 +418,33 @@ protected: }; +/* + factory functions + + */ + +AdcValueHolder make_arith_valueholder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter, + std::predicate&> auto&& validator) +{ + using val_t = traits::adc_retval_t; + + static_assert(std::predicate&>, + "INVALID VALIDATOR TYPE!!!"); + + static_assert(std::is_arithmetic_v, "GETTER MUST RETURN AN ARITHMETIC TYPE VALUE!!!"); + + return AdcValueHolder(std::forward(getter), std::forward(setter), + std::forward(validator), AdcValueHolder::_defaultTrivialConvTypes); +} + + +AdcValueHolder make_arith_valueholder(std::invocable<> auto&& getter, + std::invocable&> auto&& setter) +{ + return make_arith_valueholder(std::forward(getter), std::forward(setter), + AdcValueHolder::AdcValueHolderDummyValidator>); +} + } // namespace adc diff --git a/tests/adc_valueholder_test.cpp b/tests/adc_valueholder_test.cpp index 0019bd3..f65034d 100644 --- a/tests/adc_valueholder_test.cpp +++ b/tests/adc_valueholder_test.cpp @@ -1,32 +1,17 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include #include -// #include + #include "../common/adc_value_holder.h" -// TEST_CASE("[ADC VALUEHOLDER]") -// { -// int ch_i = 10; - -// auto getter = [&ch_i]() { return ch_i; }; -// auto setter = [&ch_i](const int& v) { ch_i = v; }; -// auto validator = [&ch_i](const int& v) { -// if (v < 0) -// return false; -// else -// return true; -// }; - -// adc::AdcValueHolder vh(getter, setter, validator); -// } - - -int main() +TEST_CASE("[ADC VALUEHOLDER]") { - int ch_i = 10; + int int_val = 10; - auto getter = [&ch_i]() { return ch_i; }; - auto setter = [&ch_i](const int& v) { ch_i = v; }; - auto validator = [&ch_i](const int& v) { + auto getter = [&int_val]() { return int_val; }; + auto setter = [&int_val](const int& v) { int_val = v; }; + auto validator = [](const int& v) { if (v < 0) return false; else @@ -34,11 +19,68 @@ int main() }; // adc::AdcValueHolder vh(getter, setter, validator); - adc::AdcValueHolder vh(getter, setter, adc::AdcValueHolder::_defaultTrivialConvTypes, validator); + adc::AdcValueHolder vh(getter, setter, validator); + auto vah = adc::make_arith_valueholder(getter, setter); vh = 77; - std::cout << "(vh = 77) => ch_i = " << ch_i << "\n"; + REQUIRE_EQ(int_val, 77); - std::cout << (double)vh << "\n"; + vh = 100; + + int res = vh; + + REQUIRE_EQ(res, 100); + + CHECK_THROWS_WITH_AS(vh = 1.1, "conversion function is not defined", std::system_error); + CHECK_THROWS_WITH_AS(vh = -3, "user value is not valid", std::system_error); + + double dv = 33.33; + vah = dv; + + REQUIRE_EQ(int_val, 33); + + vah = 100; + auto res_long = static_cast(vah); + + REQUIRE_EQ(res_long, 100ul); + + vah = -10.1234; + REQUIRE_EQ(int_val, -10); + + + /* std::string holder */ + + std::string str = "THIS IS A STRING"; + + auto sget = [&str]() { return str; }; + auto sset = [&str](const std::string& s) { str = s; }; + auto sval = [](const std::string& s) { + if (s.size()) + return true; + else + return false; + }; + + + adc::AdcValueHolder vsh(sget, sset, sval); + + vsh.addConvertFunc([](std::any& v) { v = std::string(std::any_cast(v)); }, + [](std::any& v) { + auto sval = std::any_cast(&v); + v = sval->c_str(); + }); + + + vsh = "NEW VALUE"; + + REQUIRE_EQ(str, "NEW VALUE"); + + const char* sptr = vsh; + + REQUIRE_EQ(std::strcmp(sptr, "NEW VALUE"), 0); + + using namespace std::literals; + + CHECK_THROWS_WITH_AS(vsh = ""s, "user value is not valid", std::system_error); }