Skip to content

Commit

Permalink
Improve template conditional readability with custom traits values.
Browse files Browse the repository at this point in the history
  • Loading branch information
jralls committed Aug 28, 2021
1 parent 3935f1a commit a487ca3
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 157 deletions.
61 changes: 22 additions & 39 deletions libgnucash/app-utils/gnc-option-impl.hpp
Expand Up @@ -237,6 +237,18 @@ QofInstance* qof_instance_from_string(const std::string& str,
QofInstance* qof_instance_from_guid(GncGUID*, GncOptionUIType type);
std::string qof_instance_to_string(const QofInstance* inst);

template <typename T>
struct is_QofInstanceValue
{
static constexpr bool value =
(std::is_same_v<std::decay_t<T>, GncOptionValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<T>,
GncOptionValidatedValue<const QofInstance*>>);
};

template <typename T> inline constexpr bool
is_QofInstanceValue_v = is_QofInstanceValue<T>::value;

/* These will work when m_value is a built-in class; GnuCash class and container
* values will need specialization unless they happen to define operators << and
* >>.
Expand All @@ -246,16 +258,9 @@ std::string qof_instance_to_string(const QofInstance* inst);
*/
#ifndef SWIG
template<class OptType,
typename std::enable_if_t<std::is_base_of_v<OptionClassifier,
std::decay_t<OptType>> &&
! (std::is_same_v<std::decay_t<OptType>,
GncOptionValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionValidatedValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<int>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<double>>), int> = 0>
typename std::enable_if_t<is_OptionClassifier_v<OptType> &&
! (is_QofInstanceValue_v<OptType> ||
is_RangeValue_v<OptType>), int> = 0>
std::ostream& operator<<(std::ostream& oss, const OptType& opt)
{
oss << opt.get_value();
Expand All @@ -271,10 +276,7 @@ operator<< <GncOptionValue<bool>>(std::ostream& oss,
}

template<class OptType,
typename std::enable_if_t<std::is_same_v<std::decay_t<OptType>,
GncOptionValidatedValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionValue<const QofInstance*> >, int> = 0>
typename std::enable_if_t<is_QofInstanceValue_v<OptType>, int> = 0>
inline std::ostream&
operator<< (std::ostream& oss, const OptType& opt)
{
Expand All @@ -296,16 +298,9 @@ operator<< (std::ostream& oss, const OptType& opt)
}

template<class OptType,
typename std::enable_if_t<std::is_base_of_v<OptionClassifier,
std::decay_t<OptType>> &&
!(std::is_same_v<std::decay_t<OptType>,
GncOptionValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionValidatedValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<int>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<double>>), int> = 0>
typename std::enable_if_t<is_OptionClassifier_v<OptType> &&
!(is_QofInstanceValue_v<OptType> ||
is_RangeValue_v<OptType>), int> = 0>
std::istream& operator>>(std::istream& iss, OptType& opt)
{
std::decay_t<decltype(opt.get_value())> value;
Expand All @@ -322,11 +317,7 @@ std::istream& operator>>(std::istream& iss, OptType& opt)
}

template<class OptType,
typename std::enable_if_t<std::is_same_v<std::decay_t<OptType>,
GncOptionValidatedValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionValue<const QofInstance*> >,
int> = 0>
typename std::enable_if_t<is_QofInstanceValue_v<OptType>, int> = 0>
std::istream&
operator>> (std::istream& iss, OptType& opt)
{
Expand Down Expand Up @@ -507,11 +498,7 @@ class GncOptionRangeValue : public OptionClassifier
};

template<class OptType,
typename std::enable_if_t<std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<int>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<double>>,
int> = 0>
typename std::enable_if_t<is_RangeValue_v<OptType>, int> = 0>
inline std::ostream&
operator<< (std::ostream& oss, const OptType& opt)
{
Expand All @@ -522,11 +509,7 @@ operator<< (std::ostream& oss, const OptType& opt)
}

template<class OptType,
typename std::enable_if_t<std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<int>> ||
std::is_same_v<std::decay_t<OptType>,
GncOptionRangeValue<double>>,
int> = 0>
typename std::enable_if_t<is_RangeValue_v<OptType>, int> = 0>
inline std::istream&
operator>> (std::istream& iss, OptType& opt)
{
Expand Down
150 changes: 71 additions & 79 deletions libgnucash/app-utils/gnc-option.cpp
Expand Up @@ -34,8 +34,7 @@ extern "C"
}

template <typename ValueType,
typename std::enable_if_t<!std::is_base_of_v<OptionClassifier,
std::decay_t<ValueType>>,
typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
int>>
GncOption::GncOption(const char* section, const char* name,
const char* key, const char* doc_string,
Expand All @@ -49,55 +48,56 @@ GncOption::GncOption(const char* section, const char* name,
template <typename ValueType> ValueType
GncOption::get_value() const
{
return std::visit([](const auto option)->ValueType {
if constexpr (std::is_same_v<std::decay_t<decltype(option.get_value())>, std::decay_t<ValueType>>)
return std::visit(
[](const auto option)->ValueType {
if constexpr (is_same_decayed_v<decltype(option.get_value()),
ValueType>)
return option.get_value();
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue> &&
std::is_same_v<std::decay_t<ValueType>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionDateValue>)
{
if constexpr (is_same_decayed_v<ValueType,
RelativeDatePeriod>)
return option.get_period();
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue> &&
std::is_same_v<std::decay_t<ValueType>,
size_t>)
if constexpr (std::is_same_v<ValueType, size_t>)
return option.get_period_index();
if constexpr
(std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue> &&
std::is_same_v<std::decay_t<ValueType>,
size_t>)
return ValueType{};
}
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr (std::is_same_v<ValueType, size_t>)
return option.get_index();
if constexpr
(std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue> &&
std::is_same_v<std::decay_t<ValueType>,
if constexpr (is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
return option.get_multiple();
}
return ValueType {};
}, *m_option);
}

template <typename ValueType> ValueType
GncOption::get_default_value() const
{
return std::visit([](const auto option)->ValueType {
if constexpr (std::is_same_v<std::decay_t<decltype(option.get_value())>, std::decay_t<ValueType>>)
return std::visit(
[](const auto option)->ValueType {
if constexpr (is_same_decayed_v<decltype(option.get_value()),
ValueType>)
return option.get_default_value();
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue> &&
std::is_same_v<std::decay_t<ValueType>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionDateValue>)
{
if constexpr (is_same_decayed_v<ValueType,
RelativeDatePeriod>)
return option.get_default_period();
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue> &&
std::is_same_v<std::decay_t<ValueType>,
size_t>)
if constexpr (std::is_same_v<ValueType, size_t>)
return option.get_default_period_index();
return ValueType{};
}
if constexpr
(std::is_same_v<std::decay_t<decltype(option)>,
(is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> &&
std::is_same_v<std::decay_t<ValueType>,
is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
return option.get_default_multiple();
return ValueType {};
Expand All @@ -108,26 +108,24 @@ GncOption::get_default_value() const
template <typename ValueType> void
GncOption::set_value(ValueType value)
{
std::visit([value](auto& option) {
std::visit(
[value](auto& option) {
if constexpr
(std::is_same_v<std::decay_t<decltype(option.get_value())>,
std::decay_t<ValueType>> ||
(std::is_same_v<std::decay_t<decltype(option)>,
(is_same_decayed_v<decltype(option.get_value()), ValueType> ||
(is_same_decayed_v<decltype(option),
GncOptionDateValue> &&
(std::is_same_v<std::decay_t<ValueType>,
RelativeDatePeriod> ||
std::is_same_v<std::decay_t<ValueType>, size_t>)))
(is_same_decayed_v<ValueType, RelativeDatePeriod> ||
std::is_same_v<ValueType, size_t>)))
option.set_value(value);
if constexpr
(std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr (std::is_same_v<std::decay_t<ValueType>,
if constexpr (is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
option.set_multiple(value);
else if constexpr
(std::is_same_v<ValueType, size_t> ||
std::is_same_v<std::decay_t<ValueType>, std::string> ||
is_same_decayed_v<ValueType, std::string> ||
std::is_same_v<std::remove_cv<ValueType>, char*>)
option.set_value(value);
}
Expand All @@ -137,27 +135,23 @@ GncOption::set_value(ValueType value)
template <typename ValueType> void
GncOption::set_default_value(ValueType value)
{
std::visit([value](auto& option) {
std::visit(
[value](auto& option) {
if constexpr
(std::is_same_v<std::decay_t<decltype(option.get_value())>,
std::decay_t<ValueType>> ||
(std::is_same_v<std::decay_t<decltype(option)>,
GncOptionDateValue> &&
(std::is_same_v<std::decay_t<ValueType>,
RelativeDatePeriod> ||
std::is_same_v<std::decay_t<ValueType>, size_t>)))
(is_same_decayed_v<decltype(option.get_value()), ValueType>||
(is_same_decayed_v<decltype(option), GncOptionDateValue> &&
(is_same_decayed_v<ValueType, RelativeDatePeriod> ||
std::is_same_v<ValueType, size_t>)))
option.set_default_value(value);
if constexpr
(std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
if constexpr
(std::is_same_v<std::decay_t<ValueType>,
if constexpr (is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>)
option.set_multiple(value);
option.set_default_multiple(value);
else if constexpr
(std::is_same_v<ValueType, size_t> ||
std::is_same_v<std::decay_t<ValueType>, std::string> ||
is_same_decayed_v<ValueType, std::string> ||
std::is_same_v<std::remove_cv<ValueType>, char*>)
option.set_default_value(value);
}
Expand All @@ -174,7 +168,7 @@ GncOption::get_limits(ValueType& max, ValueType& min, ValueType& step) const noe
{
std::visit([&max, &min, &step](const auto& option) {
if constexpr
(std::is_same_v<std::decay_t<decltype(option)>,
(is_same_decayed_v<decltype(option),
GncOptionRangeValue<ValueType>>)
option.get_limits(max, min, step);
}, *m_option);
Expand Down Expand Up @@ -292,8 +286,9 @@ GncOption::is_changed() const noexcept
bool
GncOption::is_multiselect() const noexcept
{
return std::visit([](const auto& option)->bool {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
return std::visit(
[](const auto& option)->bool {
if constexpr (is_same_decayed_v<decltype(option),
GncOptionAccountListValue>)
return option.is_multiselect();
else
Expand All @@ -304,16 +299,17 @@ GncOption::is_multiselect() const noexcept
template<typename ValueType> bool
GncOption::validate(ValueType value) const
{
return std::visit([value] (const auto& option) -> bool {
if constexpr ((std::is_same_v<std::decay_t<decltype(option)>,
return std::visit(
[value] (const auto& option) -> bool {
if constexpr ((is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> &&
std::is_same_v<std::decay_t<ValueType>,
is_same_decayed_v<ValueType,
std::string>) ||
(std::is_same_v<std::decay_t<decltype(option)>,
(is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> &&
std::is_same_v<std::decay_t<ValueType>,
is_same_decayed_v<ValueType,
GncMultichoiceOptionIndexVec>) ||
std::is_same_v<std::decay_t<decltype(option)>,
is_same_decayed_v<decltype(option),
GncOptionValidatedValue<ValueType>>)
return option.validate(value);
else
Expand All @@ -324,10 +320,11 @@ GncOption::validate(ValueType value) const
std::size_t
GncOption::num_permissible_values() const
{
return std::visit([] (const auto& option) -> size_t {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
return std::visit(
[] (const auto& option) -> size_t {
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> ||
std::is_same_v<std::decay_t<decltype(option)>,
is_same_decayed_v<decltype(option),
GncOptionDateValue>)
return option.num_permissible_values();
else
Expand All @@ -338,10 +335,11 @@ GncOption::num_permissible_values() const
std::size_t
GncOption::permissible_value_index(const char* value) const
{
return std::visit([&value] (const auto& option) -> size_t {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
return std::visit(
[&value] (const auto& option) -> size_t {
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue> ||
std::is_same_v<std::decay_t<decltype(option)>,
is_same_decayed_v<decltype(option),
GncOptionDateValue>)
return option.permissible_value_index(value);
else
Expand Down Expand Up @@ -393,10 +391,7 @@ bool
GncOption::is_alternate() const noexcept
{
return std::visit([](auto& option) -> bool {
if constexpr(std::is_same_v<std::decay_t<decltype(option)>,
GncOptionRangeValue<int>> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionRangeValue<double>>)
if constexpr(is_RangeValue_v<decltype(option)>)
return option.is_alternate();
return false;
}, *m_option);
Expand All @@ -406,10 +401,7 @@ void
GncOption::set_alternate(bool alt) noexcept
{
std::visit([alt](auto& option) {
if constexpr(std::is_same_v<std::decay_t<decltype(option)>,
GncOptionRangeValue<int>> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionRangeValue<double>>)
if constexpr(is_RangeValue_v<decltype(option)>)
option.set_alternate(alt);
}, *m_option);
}
Expand Down

0 comments on commit a487ca3

Please sign in to comment.