Commit ca3be93f authored by Dominik Charousset's avatar Dominik Charousset

Port config value to new sum type API

parent f1c68067
...@@ -26,11 +26,14 @@ ...@@ -26,11 +26,14 @@
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
#include "caf/default_sum_type_access.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include "caf/sum_type.hpp"
#include "caf/sum_type_access.hpp"
#include "caf/timestamp.hpp" #include "caf/timestamp.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
#include "caf/detail/comparable.hpp"
namespace caf { namespace caf {
/// A type for config parameters with similar interface to a `variant`. This /// A type for config parameters with similar interface to a `variant`. This
...@@ -38,20 +41,33 @@ namespace caf { ...@@ -38,20 +41,33 @@ namespace caf {
/// contain lists of themselves. /// contain lists of themselves.
class config_value { class config_value {
public: public:
// -- friends ----------------------------------------------------------------
friend struct default_sum_type_access<config_value>;
// -- member types -----------------------------------------------------------
using T0 = int64_t; using T0 = int64_t;
using T1 = bool; using T1 = bool;
using T2 = double; using T2 = double;
using T3 = atom_value; using T3 = atom_value;
using T4 = timespan; using T4 = timespan;
using T5 = std::string; using T5 = std::string;
using T6 = std::vector<config_value>; using T6 = std::vector<config_value>;
using T7 = std::map<std::string, config_value>;
using type0 = T0; using T7 = std::map<std::string, config_value>;
using types = detail::type_list<T0, T1, T2, T3, T4, T5, T6, T7>; using types = detail::type_list<T0, T1, T2, T3, T4, T5, T6, T7>;
using variant_type = variant<T0, T1, T2, T3, T4, T5, T6, T7>; using variant_type = detail::tl_apply_t<types, variant>;
// -- constructors, destructors, and assignment operators --------------------
config_value() = default; config_value() = default;
...@@ -78,6 +94,8 @@ public: ...@@ -78,6 +94,8 @@ public:
~config_value(); ~config_value();
// -- properties -------------------------------------------------------------
/// Converts the value to a list with one element. Does nothing if the value /// Converts the value to a list with one element. Does nothing if the value
/// already is a list. /// already is a list.
void convert_to_list(); void convert_to_list();
...@@ -86,47 +104,16 @@ public: ...@@ -86,47 +104,16 @@ public:
/// calling `convert_to_list` if needed. /// calling `convert_to_list` if needed.
void append(config_value x); void append(config_value x);
inline size_t index() const { /// Returns the underlying variant.
return data_.index(); inline variant_type& get_data() {
}
inline bool valueless_by_exception() const {
return data_.valueless_by_exception();
}
template <class Visitor>
auto apply(Visitor&& visitor) -> decltype(visitor(std::declval<T0&>())) {
return data_.apply(visitor);
}
template <class Visitor>
auto apply(Visitor&& visitor) const
-> decltype(visitor(std::declval<const T0&>())) {
return data_.apply(visitor);
}
template <int Pos>
const typename detail::tl_at<types, Pos>::type&
get(std::integral_constant<int, Pos> token) const {
return data_.get(token);
}
template <int Pos>
typename detail::tl_at<types, Pos>::type&
get(std::integral_constant<int, Pos> token) {
return data_.get(token);
}
inline variant_type& data() {
return data_; return data_;
} }
inline const variant_type& data() const { /// Returns the underlying variant.
inline const variant_type& get_data() const {
return data_; return data_;
} }
/// @endcond
private: private:
// -- auto conversion of related types --------------------------------------- // -- auto conversion of related types ---------------------------------------
...@@ -164,6 +151,12 @@ private: ...@@ -164,6 +151,12 @@ private:
variant_type data_; variant_type data_;
}; };
/// Enable `holds_alternative`, `get`, `get_if`, and `visit` for `config_value`.
/// @relates config_value
/// @relates SumType
template <>
struct sum_type_access<config_value> : default_sum_type_access<config_value> {};
/// @relates config_value /// @relates config_value
bool operator<(const config_value& x, const config_value& y); bool operator<(const config_value& x, const config_value& y);
...@@ -181,58 +174,18 @@ inline bool operator!=(const config_value& x, const config_value& y) { ...@@ -181,58 +174,18 @@ inline bool operator!=(const config_value& x, const config_value& y) {
} }
/// @relates config_value /// @relates config_value
template <class Visitor> std::string to_string(const config_value& x);
auto visit(Visitor&& f, config_value& x)
-> decltype(f(std::declval<int64_t&>())) {
return visit(std::forward<Visitor>(f), x.data());
}
/// @relates config_value
template <class Visitor>
auto visit(Visitor&& f, const config_value& x)
-> decltype(f(std::declval<const int64_t&>())) {
return visit(std::forward<Visitor>(f), x.data());
}
/// @relates config_value
template <class T>
bool holds_alternative(const config_value& x) {
return holds_alternative<T>(x.data());
}
/// @relates config_value
template <class T>
T& get(config_value& x) {
return get<T>(x.data());
}
/// @relates config_value
template <class T>
const T& get(const config_value& x) {
return get<T>(x.data());
}
/// @relates config_value
template <class T>
T* get_if(config_value* x) {
return x != nullptr ? get_if<T>(&(x->data())) : nullptr;
}
/// @relates config_value
template <class T>
const T* get_if(const config_value* x) {
return x != nullptr ? get_if<T>(&(x->data())) : nullptr;
}
/// @relates config_value template <class... Ts>
inline std::string to_string(const config_value& x) { config_value make_config_value_list(Ts&&... xs) {
return deep_to_string(x.data()); std::vector<config_value> lst{config_value{std::forward<Ts>(xs)}...};
return config_value{std::move(lst)};
} }
/// @relates config_value /// @relates config_value
template <class Inspector> template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, config_value& x) { typename Inspector::result_type inspect(Inspector& f, config_value& x) {
return f(meta::type_name("config_value"), x.data()); return f(meta::type_name("config_value"), x.get_data());
} }
} // namespace caf } // namespace caf
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
namespace caf { namespace caf {
const char* type_name_visitor_tbl[] { const char* type_name_visitor_tbl[] {
"a boolean", "a boolean",
"a float", "a float",
"a double", "a double",
"a string", "a string",
"an atom_value", "an atom_value",
...@@ -76,10 +76,12 @@ void config_option::report_type_error(size_t ln, config_value& x, ...@@ -76,10 +76,12 @@ void config_option::report_type_error(size_t ln, config_value& x,
optional<std::ostream&> out) { optional<std::ostream&> out) {
if (!out) if (!out)
return; return;
/*
type_name_visitor tnv; type_name_visitor tnv;
*out << "error in line " << ln << ": expected " *out << "error in line " << ln << ": expected "
<< expected << " found " << expected << " found "
<< visit(tnv, x) << '\n'; << visit(tnv, x) << '\n';
*/
} }
} // namespace caf } // namespace caf
...@@ -23,41 +23,6 @@ ...@@ -23,41 +23,6 @@
namespace caf { namespace caf {
namespace {
struct less_comparator {
template <class T, class U>
detail::enable_if_t<std::is_same<T, U>::value, bool>
operator()(const T& x, const U& y) const {
return x < y;
}
template <class T, class U>
detail::enable_if_t<!std::is_same<T, U>::value, bool>
operator()(const T&, const U&) const {
// Sort by type index when comparing different types.
using namespace detail;
using types = config_value::types;
return tl_index_of<types, T>::value < tl_index_of<types, U>::value;
}
};
struct equal_comparator {
template <class T, class U>
detail::enable_if_t<std::is_same<T, U>::value, bool>
operator()(const T& x, const U& y) const {
return x == y;
}
template <class T, class U>
detail::enable_if_t<!std::is_same<T, U>::value, bool>
operator()(const T&, const U&) const {
return false;
}
};
} // namespace <anonymous>
config_value::~config_value() { config_value::~config_value() {
// nop // nop
} }
...@@ -65,24 +30,27 @@ config_value::~config_value() { ...@@ -65,24 +30,27 @@ config_value::~config_value() {
void config_value::convert_to_list() { void config_value::convert_to_list() {
if (holds_alternative<T6>(data_)) if (holds_alternative<T6>(data_))
return; return;
config_value tmp{std::move(*this)}; using std::swap;
set(T6{std::move(tmp)}); config_value tmp;
swap(*this, tmp);
data_ = std::vector<config_value>{std::move(tmp)};
} }
void config_value::append(config_value x) { void config_value::append(config_value x) {
convert_to_list(); convert_to_list();
auto& xs = caf::get<T6>(data_); get<T6>(data_).emplace_back(std::move(x));
xs.emplace_back(std::move(x));
} }
bool operator<(const config_value& x, const config_value& y) { bool operator<(const config_value& x, const config_value& y) {
less_comparator cmp; return x.get_data() < y.get_data();
return visit(cmp, x.data(), y.data());
} }
bool operator==(const config_value& x, const config_value& y) { bool operator==(const config_value& x, const config_value& y) {
equal_comparator cmp; return x.get_data() == y.get_data();
return visit(cmp, x.data(), y.data()); }
std::string to_string(const config_value& x) {
return deep_to_string(x.get_data());
} }
} // namespace caf } // namespace caf
......
...@@ -47,16 +47,8 @@ CAF_TEST(default_constructed) { ...@@ -47,16 +47,8 @@ CAF_TEST(default_constructed) {
} }
CAF_TEST(list) { CAF_TEST(list) {
std::vector<config_value> xs; auto x = make_config_value_list(1, 2, 3);
xs.emplace_back(int64_t{1}); CAF_CHECK_EQUAL(to_string(x), "[1, 2, 3]");
xs.emplace_back(atom("foo"));
xs.emplace_back(string("bar"));
config_value x{xs};
CAF_CHECK_EQUAL(to_string(x), "[1, 'foo', \"bar\"]");
auto ys = xs;
xs.emplace_back(std::move(ys));
x = xs;
CAF_CHECK_EQUAL(to_string(x), "[1, 'foo', \"bar\", [1, 'foo', \"bar\"]]");
} }
CAF_TEST(convert_to_list) { CAF_TEST(convert_to_list) {
......
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