From 6c188be218540c3f022f1de90b56cd4b85b884ac Mon Sep 17 00:00:00 2001 From: Davide Basso <davide.basso@skywarder.eu> Date: Thu, 19 Dec 2024 22:01:33 +0000 Subject: [PATCH] [Units] Add more operators Operators added: unary + - and ! >> << --- src/shared/units/Units.h | 57 ++++++++++++++++++++++++++++++++-- src/tests/catch/test-units.cpp | 20 ++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/shared/units/Units.h b/src/shared/units/Units.h index f4f382139..35d6dd67d 100644 --- a/src/shared/units/Units.h +++ b/src/shared/units/Units.h @@ -24,6 +24,7 @@ #include <utils/Debug.h> +#include <ostream> #include <ratio> #include <typeinfo> @@ -32,6 +33,9 @@ namespace Boardcore namespace Units { +/** + * @brief Enumeration of the different kinds of units. + */ enum class UnitKind { Angle, @@ -43,7 +47,16 @@ enum class UnitKind Frequency, }; -// Base class to implement custom measurement units logic. +/** + * Base class to implement custom measurement units logic. + * @tparam Kind The kind of unit. + * @tparam Ratio The ratio of the unit. + * + * The Ratio template parameter is used to convert between different units of + * the same kind. For example, to convert from meters to kilometers, the ratio + * is 1/1000. + * + */ template <UnitKind Kind, class Ratio = std::ratio<1>> class Unit { @@ -56,7 +69,9 @@ public: { } - // Get the value of the unit in the specified ratio. + /** + * @brief Return the value of the unit in the target ratio. + */ template <class TargetRatio = Ratio> constexpr float value() const { @@ -74,6 +89,10 @@ public: return Unit<TargetKind, TargetRatio>(value<TargetRatio>()); } + template <UnitKind PKind, class PRatio> + friend std::istream& operator>>(std::istream& is, + Unit<PKind, PRatio>& unit); + private: float _value; }; @@ -191,5 +210,39 @@ constexpr Unit<Kind, Ratio>& operator/=(Unit<Kind, Ratio>& lhs, float rhs) return lhs; } +// Unary operators +template <UnitKind Kind, class Ratio> +constexpr Unit<Kind, Ratio> operator+(const Unit<Kind, Ratio>& unit) +{ + return Unit<Kind, Ratio>(unit.template value()); +} + +template <UnitKind Kind, class Ratio> +constexpr Unit<Kind, Ratio> operator-(const Unit<Kind, Ratio>& unit) +{ + return Unit<Kind, Ratio>(-unit.template value()); +} + +template <UnitKind Kind, class Ratio> +constexpr bool operator!(const Unit<Kind, Ratio>& unit) +{ + return !unit.template value(); +} + +// Stream operators +template <UnitKind Kind, class Ratio> +std::ostream& operator<<(std::ostream& os, const Unit<Kind, Ratio>& unit) +{ + os << unit.template value(); + return os; +} + +template <UnitKind Kind, class Ratio> +inline std::istream& operator>>(std::istream& is, Unit<Kind, Ratio>& unit) +{ + is >> unit._value; + return is; +} + } // namespace Units } // namespace Boardcore diff --git a/src/tests/catch/test-units.cpp b/src/tests/catch/test-units.cpp index b461d9fed..456aacb4a 100644 --- a/src/tests/catch/test-units.cpp +++ b/src/tests/catch/test-units.cpp @@ -30,6 +30,7 @@ #include <catch2/catch.hpp> #include <cmath> +#include <sstream> using namespace Boardcore; @@ -103,4 +104,23 @@ TEST_CASE("Units Test") REQUIRE(a == Radian(2 * PI)); a /= 2; REQUIRE(a == Radian(PI)); + + // Test unary operators + REQUIRE(+Radian(PI) == Radian(PI)); + REQUIRE(-Radian(PI) == Radian(-PI)); + REQUIRE(!Radian(PI) == false); + REQUIRE(!Radian(0) == true); + + // Test stream operators + std::ostringstream ss; + ss << 1_deg; + REQUIRE(ss.str() == "1"); + ss << 2_rad; + REQUIRE(ss.str() == "12"); + ss << 3_m; + REQUIRE(ss.str() == "123"); + + std::istringstream is("4"); + is >> a; + REQUIRE(a == 4_rad); } -- GitLab