17#include <fmt/format.h>
18#include <fmt/ranges.h>
34using PropertyValue = std::variant<bool, uint32_t, int32_t, uint64_t, int64_t, double, std::string,
35 std::vector<bool>, std::vector<uint32_t>, std::vector<int32_t>,
36 std::vector<uint64_t>, std::vector<int64_t>, std::vector<double>,
37 std::vector<std::string>>;
43 using PropertyMap = std::map<std::string_view, PropertyBase&>;
45 template <
typename T>
void setProperty(std::string_view name, T&& value) {
48 template <
typename T> T
getProperty(std::string_view name)
const {
49 return std::get<T>(m_props.at(name).get());
53 return m_props.count(name) && m_props.at(name).hasValue();
57 std::vector<std::string_view> missing;
58 for (
const auto& [name, prop] : m_props) {
59 if (!prop.hasValue()) {
60 missing.push_back(name);
68 if (!missing.empty()) {
69 throw PropertyError(fmt::format(
"Missing properties: {}", missing));
74 void registerProperty(PropertyBase& prop) {
75 if (m_props.count(prop.name())) {
76 throw PropertyError(fmt::format(
"Duplicate property name: {}", prop.name()));
78 m_props.emplace(prop.name(), prop);
106 owner->registerProperty(*
this);
109 fmt::format(
"Attempting to create Property '{}' without valid owner",
name));
125 m_value =
static_cast<value_type>(std::get<impl_type>(v));
137 operator T()
const {
return m_value; }
140 template <
typename U>
bool operator==(
const U& rhs)
const {
return m_value == rhs; }
141 template <
typename U>
bool operator!=(
const U& rhs)
const {
return m_value != rhs; }
142 template <
typename U>
bool operator>(
const U& rhs)
const {
return m_value > rhs; }
143 template <
typename U>
bool operator>=(
const U& rhs)
const {
return m_value >= rhs; }
144 template <
typename U>
bool operator<(
const U& rhs)
const {
return m_value < rhs; }
145 template <
typename U>
bool operator<=(
const U& rhs)
const {
return m_value <= rhs; }
146 template <
typename U>
decltype(
auto)
operator+(
const U& rhs)
const {
return m_value + rhs; }
147 template <
typename U>
decltype(
auto)
operator-(
const U& rhs)
const {
return m_value - rhs; }
148 template <
typename U>
decltype(
auto)
operator*(
const U& rhs)
const {
return m_value * rhs; }
149 template <
typename U>
decltype(
auto)
operator/(
const U& rhs)
const {
return m_value / rhs; }
156 requires requires(
const T& v) { v.size(); }
158 return value().size();
161 requires requires(
const T& v) { v.length(); }
163 return value().length();
166 requires requires(
const T& v) { v.empty(); }
168 return value().empty();
171 requires requires(
const T& v) { v.begin(); }
173 return value().begin();
175 decltype(
auto)
end()
const
176 requires requires(
const T& v) { v.end(); }
178 return value().end();
181 requires requires(
const T& v,
const Arg& arg) { v[arg]; }
182 decltype(
auto)
operator[](
const Arg& arg)
const {
186 requires requires(
const T& v,
const Key& key) { v.find(key); }
187 decltype(
auto)
find(
const Key& key)
const {
188 return value().find(key);
192 template <
class... Args>
193 requires std::invocable<
const T&, Args&&...>
194 decltype(
auto)
operator()(Args&&... args)
const {
195 return m_value(std::forward<Args>(args)...);
211#if __cpp_impl_three_way_comparison < 201711
212template <
class T,
class U>
218 requires requires(std::ostream& os,
const T& v) { os << v; }
220 return os << p.
value();
226struct fmt::formatter<
algorithms::Configurable::Property<T>> : fmt::formatter<T> {
227 template <
class FormatContext>
229 return fmt::formatter<T>::format(p.
value(), ctx);
232template <
class T,
class Char>
233struct fmt::is_range<
algorithms::Configurable::Property<T>, Char> : std::false_type {};
virtual void set(const PropertyValue &v)=0
virtual PropertyValue get() const =0
PropertyBase(std::string_view name, std::string_view description)
bool operator>(const U &rhs) const
detail::upcast_type_t< T > impl_type
const value_type & value() const
bool operator>=(const U &rhs) const
Property(Configurable *owner, std::string_view name, std::string_view description)
Property(const Property &)=default
Property & operator=(const Property &)=default
decltype(auto) size() const
bool operator!=(const U &rhs) const
decltype(auto) begin() const
bool operator<=(const U &rhs) const
bool operator==(const U &rhs) const
virtual PropertyValue get() const
decltype(auto) length() const
decltype(auto) find(const Key &key) const
bool operator<(const U &rhs) const
Property(Configurable *owner, std::string_view name, const value_type &v, std::string_view description)
decltype(auto) empty() const
decltype(auto) end() const
virtual void set(const PropertyValue &v)
void setProperty(std::string_view name, T &&value)
const PropertyMap & getProperties() const
bool hasProperty(std::string_view name) const
auto missingProperties() const
std::map< std::string_view, PropertyBase & > PropertyMap
T getProperty(std::string_view name) const
Error(std::string_view msg, std::string_view type="algorithms::Error")
std::string_view description() const
NameMixin(std::string_view name, std::string_view description)
std::string_view name() const
PropertyError(std::string_view msg)
typename upcast_type< std::remove_cvref_t< T > >::type upcast_type_t
Configurable PropertyMixin
std::variant< bool, uint32_t, int32_t, uint64_t, int64_t, double, std::string, std::vector< bool >, std::vector< uint32_t >, std::vector< int32_t >, std::vector< uint64_t >, std::vector< int64_t >, std::vector< double >, std::vector< std::string > > PropertyValue
bool operator==(const U &rhs, const algorithms::Configurable::Property< T > &p)
std::ostream & operator<<(std::ostream &os, const algorithms::Configurable::Property< T > &p)