Unverified Commit abbb245c authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #920

Fix holds_alternative and get_if for settings
parents f456a5da cf2df9b2
......@@ -217,10 +217,39 @@ private:
// -- SumType-like access ------------------------------------------------------
template <class T>
struct default_config_value_access {
static bool is(const config_value& x) {
return holds_alternative<T>(x.get_data());
}
static const T* get_if(const config_value* x) {
return caf::get_if<T>(&(x->get_data()));
}
static T get(const config_value& x) {
return caf::get<T>(x.get_data());
}
};
/// @relates config_value
template <class T>
struct config_value_access;
#define CAF_DEFAULT_CONFIG_VALUE_ACCESS(type) \
template <> \
struct config_value_access<type> : default_config_value_access<type> {}
CAF_DEFAULT_CONFIG_VALUE_ACCESS(bool);
CAF_DEFAULT_CONFIG_VALUE_ACCESS(double);
CAF_DEFAULT_CONFIG_VALUE_ACCESS(atom_value);
CAF_DEFAULT_CONFIG_VALUE_ACCESS(timespan);
CAF_DEFAULT_CONFIG_VALUE_ACCESS(std::string);
CAF_DEFAULT_CONFIG_VALUE_ACCESS(config_value::list);
CAF_DEFAULT_CONFIG_VALUE_ACCESS(config_value::dictionary);
#undef CAF_DEFAULT_CONFIG_VALUE_ACCESS
/// Delegates to config_value_access for all specialized versions.
template <class T, bool IsIntegral = std::is_integral<T>::value>
struct select_config_value_access {
......@@ -328,8 +357,6 @@ struct sum_type_access<config_value> {
template <>
struct config_value_access<float> {
static constexpr bool specialized = true;
static bool is(const config_value& x) {
return holds_alternative<double>(x.get_data());
}
......@@ -353,8 +380,6 @@ template <class T>
struct config_value_access<std::vector<T>> {
using vector_type = std::vector<T>;
static constexpr bool specialized = true;
static bool is(const config_value& x) {
auto lst = caf::get_if<config_value::list>(&x);
if (lst != nullptr) {
......@@ -396,8 +421,6 @@ template <class... Ts>
struct config_value_access<std::tuple<Ts...>> {
using tuple_type = std::tuple<Ts...>;
static constexpr bool specialized = true;
static bool is(const config_value& x) {
if (auto lst = caf::get_if<config_value::list>(&x)) {
if (lst->size() != sizeof...(Ts))
......@@ -469,8 +492,6 @@ struct config_value_access<dictionary<V>> {
using kvp = std::pair<const std::string, config_value>;
static constexpr bool specialized = true;
static bool is(const config_value& x) {
auto lst = caf::get_if<config_value::dictionary>(&x);
if (lst != nullptr) {
......
......@@ -44,6 +44,16 @@ optional<T> get_if(const settings* xs, string_view name) {
return none;
}
/// Returns whether `xs` associates a value of type `T` to `name`.
/// @relates config_value
template <class T>
bool holds_alternative(const settings& xs, string_view name) {
using access = select_config_value_access_t<T>;
if (auto value = get_if(&xs, name))
return access::is(*value);
return false;
}
template <class T>
T get(const settings& xs, string_view name) {
auto result = get_if<T>(&xs, name);
......
......@@ -82,8 +82,51 @@ const config_value& unpack(const settings& x, string_view key,
keys...);
}
struct foobar {
int foo = 0;
int bar = 0;
};
} // namespace
namespace caf {
// Enable users to configure foobar's like this:
// my-value {
// foo = 42
// bar = 23
// }
template <>
struct config_value_access<foobar> {
static bool is(const config_value& x) {
auto dict = caf::get_if<config_value::dictionary>(&x);
if (dict != nullptr) {
return caf::get_if<int>(dict, "foo") != none
&& caf::get_if<int>(dict, "bar") != none;
}
return false;
}
static optional<foobar> get_if(const config_value* x) {
foobar result;
if (!is(*x))
return none;
const auto& dict = caf::get<config_value::dictionary>(*x);
result.foo = caf::get<int>(dict, "foo");
result.bar = caf::get<int>(dict, "bar");
return result;
}
static foobar get(const config_value& x) {
auto result = get_if(&x);
if (!result)
CAF_RAISE_ERROR("invalid type found");
return std::move(*result);
}
};
} // namespace caf
CAF_TEST_FIXTURE_SCOPE(settings_tests, fixture)
CAF_TEST(put) {
......@@ -159,4 +202,14 @@ CAF_TEST(get_or) {
CAF_CHECK_EQUAL(get_or(x, "goodbye", "nobody"), "nobody"_s);
}
CAF_TEST(custom type) {
put(x, "my-value.foo", 42);
put(x, "my-value.bar", 24);
CAF_REQUIRE(holds_alternative<foobar>(x, "my-value"));
CAF_REQUIRE(get_if<foobar>(&x, "my-value") != caf::none);
auto fb = get<foobar>(x, "my-value");
CAF_CHECK_EQUAL(fb.foo, 42);
CAF_CHECK_EQUAL(fb.bar, 24);
}
CAF_TEST_FIXTURE_SCOPE_END()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment