Commit ca3be93f authored by Dominik Charousset's avatar Dominik Charousset

Port config value to new sum type API

parent f1c68067
......@@ -26,11 +26,14 @@
#include "caf/atom.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/variant.hpp"
#include "caf/detail/comparable.hpp"
namespace caf {
/// A type for config parameters with similar interface to a `variant`. This
......@@ -38,20 +41,33 @@ namespace caf {
/// contain lists of themselves.
class config_value {
public:
// -- friends ----------------------------------------------------------------
friend struct default_sum_type_access<config_value>;
// -- member types -----------------------------------------------------------
using T0 = int64_t;
using T1 = bool;
using T2 = double;
using T3 = atom_value;
using T4 = timespan;
using T5 = std::string;
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 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;
......@@ -78,6 +94,8 @@ public:
~config_value();
// -- properties -------------------------------------------------------------
/// Converts the value to a list with one element. Does nothing if the value
/// already is a list.
void convert_to_list();
......@@ -86,47 +104,16 @@ public:
/// calling `convert_to_list` if needed.
void append(config_value x);
inline size_t index() const {
return data_.index();
}
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() {
/// Returns the underlying variant.
inline variant_type& get_data() {
return data_;
}
inline const variant_type& data() const {
/// Returns the underlying variant.
inline const variant_type& get_data() const {
return data_;
}
/// @endcond
private:
// -- auto conversion of related types ---------------------------------------
......@@ -164,6 +151,12 @@ private:
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
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
template <class Visitor>
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;
}
std::string to_string(const config_value& x);
/// @relates config_value
inline std::string to_string(const config_value& x) {
return deep_to_string(x.data());
template <class... Ts>
config_value make_config_value_list(Ts&&... xs) {
std::vector<config_value> lst{config_value{std::forward<Ts>(xs)}...};
return config_value{std::move(lst)};
}
/// @relates config_value
template <class Inspector>
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
......
......@@ -23,8 +23,8 @@
namespace caf {
const char* type_name_visitor_tbl[] {
"a boolean",
"a float",
"a boolean",
"a float",
"a double",
"a string",
"an atom_value",
......@@ -76,10 +76,12 @@ void config_option::report_type_error(size_t ln, config_value& x,
optional<std::ostream&> out) {
if (!out)
return;
/*
type_name_visitor tnv;
*out << "error in line " << ln << ": expected "
<< expected << " found "
<< visit(tnv, x) << '\n';
*/
}
} // namespace caf
......@@ -23,41 +23,6 @@
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() {
// nop
}
......@@ -65,24 +30,27 @@ config_value::~config_value() {
void config_value::convert_to_list() {
if (holds_alternative<T6>(data_))
return;
config_value tmp{std::move(*this)};
set(T6{std::move(tmp)});
using std::swap;
config_value tmp;
swap(*this, tmp);
data_ = std::vector<config_value>{std::move(tmp)};
}
void config_value::append(config_value x) {
convert_to_list();
auto& xs = caf::get<T6>(data_);
xs.emplace_back(std::move(x));
get<T6>(data_).emplace_back(std::move(x));
}
bool operator<(const config_value& x, const config_value& y) {
less_comparator cmp;
return visit(cmp, x.data(), y.data());
return x.get_data() < y.get_data();
}
bool operator==(const config_value& x, const config_value& y) {
equal_comparator cmp;
return visit(cmp, x.data(), y.data());
return x.get_data() == y.get_data();
}
std::string to_string(const config_value& x) {
return deep_to_string(x.get_data());
}
} // namespace caf
......
......@@ -47,16 +47,8 @@ CAF_TEST(default_constructed) {
}
CAF_TEST(list) {
std::vector<config_value> xs;
xs.emplace_back(int64_t{1});
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\"]]");
auto x = make_config_value_list(1, 2, 3);
CAF_CHECK_EQUAL(to_string(x), "[1, 2, 3]");
}
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