diff options
Diffstat (limited to 'nihil.ucl/real.ccm')
| -rw-r--r-- | nihil.ucl/real.ccm | 151 |
1 files changed, 89 insertions, 62 deletions
diff --git a/nihil.ucl/real.ccm b/nihil.ucl/real.ccm index f425a9a..b432617 100644 --- a/nihil.ucl/real.ccm +++ b/nihil.ucl/real.ccm @@ -1,78 +1,106 @@ -/* - * This source code is released into the public domain. - */ - +// This source code is released into the public domain. module; -#include <compare> -#include <expected> -#include <format> -#include <utility> - #include <ucl.h> export module nihil.ucl:real; +import nihil.std; +import nihil.core; import :object; import :type; namespace nihil::ucl { -export struct real final : object { +export struct real final : object +{ using contained_type = double; - inline static constexpr object_type ucl_type = object_type::real; + static constexpr object_type ucl_type = object_type::real; - /* - * Create a real holding the value 0. Throws std::system_error - * on failure. - */ - real(); + // Create a real holding the value 0. Throws std::system_error + // on failure. + real() + : real(0) + { + } - /* - * Create a real holding a specific value. Throws std::system_error - * on failure. - */ - explicit real(contained_type value); + // Create a real holding a specific value. Throws std::system_error + // on failure. + explicit real(contained_type value) + : real(noref, [&] { + auto *uobj = ::ucl_object_fromdouble(value); + if (uobj == nullptr) + throw std::system_error(std::make_error_code(sys_error())); + return uobj; + }()) + { + } - /* - * Create a new real from a UCL object. Throws type_mismatch - * on failure. - */ - real(ref_t, ::ucl_object_t const *uobj); - real(noref_t, ::ucl_object_t *uobj); + // Create a new real from a UCL object. Throws type_mismatch + // on failure. + real(ref_t, ::ucl_object_t const *uobj) + : object(nihil::ucl::ref, ensure_ucl_type(uobj, real::ucl_type)) + { + } + + real(noref_t, ::ucl_object_t *uobj) + : object(nihil::ucl::noref, ensure_ucl_type(uobj, real::ucl_type)) + { + } // Return the value of this real. - [[nodiscard]] auto value(this real const &self) -> contained_type; -}; + [[nodiscard]] auto value(this real const &self) -> contained_type + { + auto v = contained_type{}; + auto const *uobj = self.get_ucl_object(); + + if (::ucl_object_todouble_safe(uobj, &v)) + return v; -/* - * Real constructors. These return an error instead of throwing. - */ + throw std::runtime_error("ucl_object_todouble_safe failed"); + } -export [[nodiscard]] auto -make_real(real::contained_type = 0) -> std::expected<real, error>; +private: + // + // Comparison operators. + // -/* - * Comparison operators. - */ + [[nodiscard]] friend auto operator==(real const &a, real const &b) -> bool + { + return a.value() == b.value(); + } -export [[nodiscard]] auto operator== (real const &a, real const &b) -> bool; + [[nodiscard]] friend auto operator<=>(real const &a, real const &b) -> std::partial_ordering + { + return a.value() <=> b.value(); + } -export [[nodiscard]] auto operator== (real const &a, - real::contained_type b) -> bool; + [[nodiscard]] friend auto operator==(real const &a, real::contained_type b) -> bool + { + return a.value() == b; + } -export [[nodiscard]] auto operator<=> (real const &a, real const &b) - -> std::partial_ordering; + [[nodiscard]] friend auto + operator<=>(real const &a, real::contained_type b) -> std::partial_ordering + { + return a.value() <=> b; + } +}; -export [[nodiscard]] auto operator<=> (real const &a, real::contained_type b) - -> std::partial_ordering; +// Real constructor. This returns an error instead of throwing. +export [[nodiscard]] auto make_real(real::contained_type value = 0) -> std::expected<real, error> +{ + auto *uobj = ::ucl_object_fromdouble(value); + if (uobj == nullptr) + return std::unexpected(error(errc::failed_to_create_object, error(sys_error()))); -/* - * Literal operator. - */ + return real(noref, uobj); +} + +// Literal operator. inline namespace literals { -export constexpr auto operator""_ucl (long double d) -> real +export constexpr auto operator""_ucl(long double d) -> real { if (d > static_cast<long double>(std::numeric_limits<double>::max()) || d < static_cast<long double>(std::numeric_limits<double>::min())) @@ -80,32 +108,31 @@ export constexpr auto operator""_ucl (long double d) -> real return real(static_cast<double>(d)); } -} // namespace nihil::ucl::literals +} // namespace literals } // namespace nihil::ucl -namespace nihil { inline namespace literals { - export using namespace ::nihil::ucl::literals; -}} // namespace nihil::literals +namespace nihil { +inline namespace literals { +export using namespace ::nihil::ucl::literals; +} +} // namespace nihil -/* - * std::formatter for a real. This provides the same format operations - * as std::formatter<double>; - */ -export template<> +// std::formatter for a real. This provides the same format operations +// as std::formatter<double>; +export template <> struct std::formatter<nihil::ucl::real, char> { std::formatter<double> base_formatter; - template<class ParseContext> - constexpr ParseContext::iterator parse(ParseContext& ctx) + template <class ParseContext> + constexpr auto parse(ParseContext &ctx) -> ParseContext::iterator { return base_formatter.parse(ctx); } - template<class FmtContext> - FmtContext::iterator format(nihil::ucl::real const &o, - FmtContext& ctx) const + template <class FmtContext> + auto format(nihil::ucl::real const &o, FmtContext &ctx) const -> FmtContext::iterator { return base_formatter.format(o.value(), ctx); } |
