Improve template conditional readability with custom traits values.

This commit is contained in:
John Ralls
2021-08-25 12:16:15 -07:00
parent 3935f1a91b
commit a487ca3f98
4 changed files with 165 additions and 157 deletions

View File

@@ -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
* >>.
@@ -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();
@@ -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)
{
@@ -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;
@@ -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)
{
@@ -507,11 +498,7 @@ private:
};
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)
{
@@ -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)
{

View File

@@ -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,
@@ -49,31 +48,30 @@ 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);
}
@@ -81,23 +79,25 @@ GncOption::get_value() const
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 {};
@@ -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);
}
@@ -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);
}
@@ -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);
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
@@ -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);
}

View File

@@ -53,6 +53,38 @@ template <typename ValueType> class GncOptionRangeValue;
template <typename ValueType> class GncOptionValidatedValue;
class GncOptionDateValue;
template <typename T>
struct is_OptionClassifier
{
static constexpr bool value =
std::is_base_of_v<OptionClassifier, std::decay_t<T>>;
};
template <typename T> inline constexpr bool
is_OptionClassifier_v = is_OptionClassifier<T>::value;
template <typename T, typename U>
struct is_same_decayed
{
static constexpr bool value = std::is_same_v<std::decay_t<T>,
std::decay_t<U>>;
};
template <typename T, typename U> inline constexpr bool
is_same_decayed_v = is_same_decayed<T, U>::value;
template <typename T>
struct is_RangeValue
{
static constexpr bool value =
(is_same_decayed_v<T, GncOptionRangeValue<int>> ||
is_same_decayed_v<T, GncOptionRangeValue<double>>);
};
template <typename T> inline constexpr bool
is_RangeValue_v = is_RangeValue<T>::value;
using GncOptionVariant = std::variant<GncOptionValue<std::string>,
GncOptionValue<bool>,
GncOptionValue<int64_t>,
@@ -82,14 +114,13 @@ class GncOption
{
public:
template <typename OptionType,
typename std::enable_if_t<std::is_base_of_v<OptionClassifier,
std::decay_t<OptionType>>,
typename std::enable_if_t<is_OptionClassifier_v<OptionType>,
int> = 0>
GncOption(OptionType option) :
m_option{std::make_unique<GncOptionVariant>(option)} {}
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> = 0>
GncOption(const char* section, const char* name,
const char* key, const char* doc_string,

View File

@@ -263,7 +263,7 @@ scm_color_list_to_string(SCM list)
template <typename ValueType> inline ValueType
scm_to_value(SCM new_value)
{
if constexpr (std::is_same_v<std::decay_t<ValueType>, SCM>)
if constexpr (is_same_decayed_v<ValueType, SCM>)
return new_value;
return ValueType{};
}
@@ -816,7 +816,26 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
return scm_cons(desig, scm_from_int(val));
}
%}
template <typename T>
struct is_MultichoiceOrRange
{
static constexpr bool value =
is_same_decayed_v<T, GncOptionMultichoiceValue> ||
is_same_decayed_v<T, GncOptionRangeValue<int>>;
};
template <typename T>
inline constexpr bool is_MultichoiceOrRange_v = is_MultichoiceOrRange<T>::value;
template <typename ValueType>
inline SCM return_scm_value(ValueType value)
{
if constexpr (is_same_decayed_v<ValueType, SCM>)
return value;
return scm_from_value(static_cast<ValueType>(value));
}
%}
%ignore GncOptionDBCallback;
%include "gnc-option-date.hpp"
@@ -840,16 +859,10 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
if (!$self)
return SCM_BOOL_F;
return std::visit([](const auto& option)->SCM {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionRangeValue<int>>)
if constexpr (is_MultichoiceOrRange_v<decltype(option)>)
return get_scm_value(option);
auto value{option.get_value()};
if constexpr (std::is_same_v<std::decay_t<decltype(value)>,
SCM>)
return value;
return scm_from_value(static_cast<decltype(value)>(value));
return return_scm_value(value);
}, swig_get_option($self));
}
SCM get_scm_default_value()
@@ -857,25 +870,20 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
if (!$self)
return SCM_BOOL_F;
return std::visit([](const auto& option)->SCM {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionRangeValue<int>>)
if constexpr (is_MultichoiceOrRange_v<decltype(option)>)
return get_scm_default_value(option);
auto value{option.get_default_value()};
if constexpr (std::is_same_v<std::decay_t<decltype(value)>,
SCM>)
return value;
return scm_from_value(static_cast<decltype(value)>(value));
return return_scm_value(value);
}, swig_get_option($self));
}
void set_value_from_scm(SCM new_value)
{
if (!$self)
return;
try {
std::visit([new_value](auto& option) {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionDateValue>)
{
if (scm_date_absolute(new_value))
@@ -885,14 +893,14 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
return;
}
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
option.set_multiple(scm_to_multichoices(new_value, option));
return;
}
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionRangeValue<int>>)
{
if (scm_is_pair(new_value))
@@ -901,10 +909,7 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
option.set_value(scm_to_int(new_value));
return;
}
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionValidatedValue<const QofInstance*>>)
if constexpr (is_QofInstanceValue_v<decltype(option)>)
{
if (scm_is_string(new_value))
{
@@ -937,7 +942,7 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
return;
try {
std::visit([new_value](auto& option) {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionDateValue>)
{
if (scm_date_absolute(new_value))
@@ -946,14 +951,14 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
option.set_default_value(scm_relative_date_get_period(new_value));
return;
}
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
{
option.set_default_multiple(scm_to_multichoices(new_value,
option));
return;
}
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
if constexpr (is_same_decayed_v<decltype(option),
GncOptionRangeValue<int>>)
{
if (scm_is_pair(new_value))
@@ -962,10 +967,7 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
option.set_default_value(scm_to_int(new_value));
return;
}
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionValue<const QofInstance*>> ||
std::is_same_v<std::decay_t<decltype(option)>,
GncOptionValidatedValue<const QofInstance*>>)
if constexpr (is_QofInstanceValue_v<decltype(option)>)
{
if (scm_is_string(new_value))
{
@@ -996,11 +998,11 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
if (!self)
return SCM_BOOL_F;
return std::visit([](const auto& option)->SCM {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionMultichoiceValue>)
if constexpr (is_same_decayed_v<decltype(option),
GncOptionMultichoiceValue>)
return scm_c_eval_string("'multichoice");
else if constexpr (std::is_same_v<decltype(option.get_value()),
bool>)
bool>)
return scm_c_eval_string("'boolean");
else
return SCM_BOOL_F;