Commit 17a85cab authored by Dominik Charousset's avatar Dominik Charousset

Use if constexpr where appropriate

parent d5b15662
...@@ -52,166 +52,166 @@ namespace caf { ...@@ -52,166 +52,166 @@ namespace caf {
/// type is not implemented as a simple variant alias because variants cannot /// type is not implemented as a simple variant alias because variants cannot
/// contain lists of themselves. /// contain lists of themselves.
class CAF_CORE_EXPORT config_value { class CAF_CORE_EXPORT config_value {
public: public:
// -- member types ----------------------------------------------------------- // -- member types -----------------------------------------------------------
using integer = int64_t; using integer = int64_t;
using boolean = bool; using boolean = bool;
using real = double; using real = double;
using timespan = caf::timespan; using timespan = caf::timespan;
using string = std::string; using string = std::string;
using list = std::vector<config_value>; using list = std::vector<config_value>;
using dictionary = caf::dictionary<config_value>; using dictionary = caf::dictionary<config_value>;
using types = detail::type_list<integer, boolean, real, timespan, uri, string, using types = detail::type_list<integer, boolean, real, timespan, uri, string,
list, dictionary>; list, dictionary>;
using variant_type = detail::tl_apply_t<types, variant>; using variant_type = detail::tl_apply_t<types, variant>;
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
config_value() = default; config_value() = default;
config_value(config_value&& other) = default; config_value(config_value&& other) = default;
config_value(const config_value& other) = default; config_value(const config_value& other) = default;
template <class T, class E = detail::enable_if_t< template <class T, class E = detail::enable_if_t<
!std::is_same<detail::decay_t<T>, config_value>::value>> !std::is_same<detail::decay_t<T>, config_value>::value>>
explicit config_value(T&& x) { explicit config_value(T&& x) {
set(std::forward<T>(x)); set(std::forward<T>(x));
} }
config_value& operator=(config_value&& other) = default; config_value& operator=(config_value&& other) = default;
config_value& operator=(const config_value& other) = default; config_value& operator=(const config_value& other) = default;
template <class T, class E = detail::enable_if_t< template <class T, class E = detail::enable_if_t<
!std::is_same<detail::decay_t<T>, config_value>::value>> !std::is_same<detail::decay_t<T>, config_value>::value>>
config_value& operator=(T&& x) { config_value& operator=(T&& x) {
set(std::forward<T>(x)); set(std::forward<T>(x));
return *this; return *this;
} }
~config_value(); ~config_value();
// -- parsing ---------------------------------------------------------------- // -- parsing ----------------------------------------------------------------
/// Tries to parse a value from `str`. /// Tries to parse a value from `str`.
static expected<config_value> static expected<config_value>
parse(string_view::iterator first, string_view::iterator last); parse(string_view::iterator first, string_view::iterator last);
/// Tries to parse a value from `str`. /// Tries to parse a value from `str`.
static expected<config_value> parse(string_view str); static expected<config_value> parse(string_view str);
// -- properties ------------------------------------------------------------- // -- 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();
/// Returns the value as a list, converting it to one if needed. /// Returns the value as a list, converting it to one if needed.
list& as_list(); list& as_list();
/// Returns the value as a dictionary, converting it to one if needed. /// Returns the value as a dictionary, converting it to one if needed.
dictionary& as_dictionary(); dictionary& as_dictionary();
/// Appends `x` to a list. Converts this config value to a list first by /// Appends `x` to a list. Converts this config value to a list first by
/// calling `convert_to_list` if needed. /// calling `convert_to_list` if needed.
void append(config_value x); void append(config_value x);
/// Returns a human-readable type name of the current value. /// Returns a human-readable type name of the current value.
const char* type_name() const noexcept; const char* type_name() const noexcept;
/// Returns the underlying variant. /// Returns the underlying variant.
variant_type& get_data() { variant_type& get_data() {
return data_; return data_;
} }
/// Returns the underlying variant. /// Returns the underlying variant.
const variant_type& get_data() const { const variant_type& get_data() const {
return data_; return data_;
} }
/// Returns a pointer to the underlying variant. /// Returns a pointer to the underlying variant.
variant_type* get_data_ptr() { variant_type* get_data_ptr() {
return &data_; return &data_;
} }
/// Returns a pointer to the underlying variant. /// Returns a pointer to the underlying variant.
const variant_type* get_data_ptr() const { const variant_type* get_data_ptr() const {
return &data_; return &data_;
} }
private: private:
// -- properties ------------------------------------------------------------- // -- properties -------------------------------------------------------------
static const char* type_name_at_index(size_t index) noexcept; static const char* type_name_at_index(size_t index) noexcept;
// -- auto conversion of related types --------------------------------------- // -- auto conversion of related types ---------------------------------------
void set(bool x) { void set(bool x) {
data_ = x; data_ = x;
} }
void set(float x) { void set(float x) {
data_ = static_cast<double>(x); data_ = static_cast<double>(x);
} }
void set(const char* x) { void set(const char* x) {
data_ = std::string{x}; data_ = std::string{x};
} }
void set(string_view x) { void set(string_view x) {
data_ = std::string{x.begin(), x.end()}; data_ = std::string{x.begin(), x.end()};
} }
template <class T> template <class T>
detail::enable_if_t< detail::enable_if_t<
detail::is_one_of<T, real, timespan, uri, string, list, dictionary>::value> detail::is_one_of<T, real, timespan, uri, string, list, dictionary>::value>
set(T x) { set(T x) {
data_ = std::move(x); data_ = std::move(x);
} }
template <class T> template <class T>
void set_range(T& xs, std::true_type) { void set_range(T& xs, std::true_type) {
auto& dict = as_dictionary(); auto& dict = as_dictionary();
dict.clear(); dict.clear();
for (auto& kvp : xs) for (auto& kvp : xs)
dict.emplace(kvp.first, std::move(kvp.second)); dict.emplace(kvp.first, std::move(kvp.second));
} }
template <class T> template <class T>
void set_range(T& xs, std::false_type) { void set_range(T& xs, std::false_type) {
auto& ls = as_list(); auto& ls = as_list();
ls.clear(); ls.clear();
ls.insert(ls.end(), std::make_move_iterator(xs.begin()), ls.insert(ls.end(), std::make_move_iterator(xs.begin()),
std::make_move_iterator(xs.end())); std::make_move_iterator(xs.end()));
} }
template <class T> template <class T>
detail::enable_if_t<detail::is_iterable<T>::value detail::enable_if_t<detail::is_iterable<T>::value
&& !detail::is_one_of<T, string, list, dictionary>::value> && !detail::is_one_of<T, string, list, dictionary>::value>
set(T xs) { set(T xs) {
using value_type = typename T::value_type; using value_type = typename T::value_type;
detail::bool_token<detail::is_pair<value_type>::value> is_map_type; detail::bool_token<detail::is_pair<value_type>::value> is_map_type;
set_range(xs, is_map_type); set_range(xs, is_map_type);
} }
template <class T> template <class T>
detail::enable_if_t<std::is_integral<T>::value> set(T x) { detail::enable_if_t<std::is_integral<T>::value> set(T x) {
data_ = static_cast<int64_t>(x); data_ = static_cast<int64_t>(x);
} }
// -- member variables ------------------------------------------------------- // -- member variables -------------------------------------------------------
variant_type data_; variant_type data_;
}; };
// -- convenience constants ---------------------------------------------------- // -- convenience constants ----------------------------------------------------
...@@ -251,9 +251,9 @@ struct default_config_value_access { ...@@ -251,9 +251,9 @@ struct default_config_value_access {
} }
template <class Nested> template <class Nested>
static void parse_cli(string_parser_state& ps, T& x, Nested) { static void parse_cli(string_parser_state& ps, T& x, Nested) {
detail::parse(ps, x); detail::parse(ps, x);
} }
}; };
struct config_value_access_unspecialized {}; struct config_value_access_unspecialized {};
...@@ -265,7 +265,7 @@ struct config_value_access : config_value_access_unspecialized {}; ...@@ -265,7 +265,7 @@ struct config_value_access : config_value_access_unspecialized {};
#define CAF_DEFAULT_CONFIG_VALUE_ACCESS(type, name) \ #define CAF_DEFAULT_CONFIG_VALUE_ACCESS(type, name) \
template <> \ template <> \
struct CAF_CORE_EXPORT config_value_access<type> \ struct CAF_CORE_EXPORT config_value_access<type> \
: default_config_value_access<type> { \ : default_config_value_access<type> { \
static std::string type_name() { \ static std::string type_name() { \
return name; \ return name; \
} \ } \
...@@ -305,7 +305,7 @@ struct CAF_CORE_EXPORT config_value_access<std::string> { ...@@ -305,7 +305,7 @@ struct CAF_CORE_EXPORT config_value_access<std::string> {
template <bool IsNested> template <bool IsNested>
static void parse_cli(string_parser_state& ps, std::string& x, static void parse_cli(string_parser_state& ps, std::string& x,
std::integral_constant<bool, IsNested>) { std::integral_constant<bool, IsNested>) {
if (IsNested) if constexpr (IsNested)
detail::parse_element(ps, x, ",={}[]"); detail::parse_element(ps, x, ",={}[]");
else else
detail::parse(ps, x); detail::parse(ps, x);
......
...@@ -52,25 +52,14 @@ config_value get_impl(const void* ptr) { ...@@ -52,25 +52,14 @@ config_value get_impl(const void* ptr) {
return config_value{trait::convert(*reinterpret_cast<const T*>(ptr))}; return config_value{trait::convert(*reinterpret_cast<const T*>(ptr))};
} }
template <class T>
typename std::enable_if<detail::has_clear_member<T>::value>::type
clear_before_parsing(T& xs) {
xs.clear();
}
template <class T>
typename std::enable_if<!detail::has_clear_member<T>::value>::type
clear_before_parsing(T&) {
// nop
}
template <class T> template <class T>
expected<config_value> parse_impl(T* ptr, string_view str) { expected<config_value> parse_impl(T* ptr, string_view str) {
if (!ptr) { if (!ptr) {
T tmp; T tmp;
return parse_impl(&tmp, str); return parse_impl(&tmp, str);
} }
clear_before_parsing(*ptr); if constexpr (detail::has_clear_member<T>::value)
ptr->clear();
using trait = select_config_value_access_t<T>; using trait = select_config_value_access_t<T>;
string_parser_state ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
trait::parse_cli(ps, *ptr, top_level_cli_parsing); trait::parse_cli(ps, *ptr, top_level_cli_parsing);
......
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