Skip to content

Commit

Permalink
add std::format support to units, Temperature, and Angle
Browse files Browse the repository at this point in the history
  • Loading branch information
SizzinSeal committed Jan 7, 2025
1 parent 0515c4d commit f802474
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 22 deletions.
7 changes: 7 additions & 0 deletions include/units/Angle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ template <> struct LookupName<Quantity<std::ratio<0>, std::ratio<0>, std::ratio<
using Named = Angle;
};

template <> struct std::formatter<Angle> : std::formatter<double> {
auto format(const Angle& number, std::format_context& ctx) const {
auto formatted_double = std::formatter<double>::format(number.internal(), ctx);
return std::format_to(formatted_double, "_stRad");
}
};

inline std::ostream& operator<<(std::ostream& os, const Angle& quantity) {
os << quantity.internal() << " rad";
return os;
Expand Down
6 changes: 6 additions & 0 deletions include/units/Temperature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ template <> struct LookupName<Quantity<std::ratio<0>, std::ratio<0>, std::ratio<
using Named = Temperature;
};

template <> struct std::formatter<Temperature> : std::formatter<double> {
auto format(const Temperature& quantity, std::format_context& ctx) const {
return std::format_to(ctx.out(), "{}_k", quantity.internal());
}
};

inline std::ostream& operator<<(std::ostream& os, const Temperature& quantity) {
os << quantity.internal() << " k";
return os;
Expand Down
34 changes: 20 additions & 14 deletions include/units/units.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,9 @@ template <isQuantity Q, isQuantity R> constexpr bool operator>(const Q& lhs, con
std::ratio<j>, std::ratio<n>>(static_cast<double>(value))); \
} \
template <> struct std::formatter<Name> : std::formatter<double> { \
auto format(const Name& quantity, std::format_context& ctx) const { \
return std::format_to(ctx.out(), "{}_##suffix", quantity.internal()); \
auto format(const Name& number, std::format_context& ctx) const { \
auto formatted_double = std::formatter<double>::format(number.internal(), ctx); \
return std::format_to(formatted_double, "_" #suffix); \
} \
}; \
inline std::ostream& operator<<(std::ostream& os, const Name& quantity) { \
Expand Down Expand Up @@ -610,25 +611,30 @@ template <isQuantity Q, isQuantity R> constexpr Q round(const Q& lhs, const R& r

// Convert an angular unit `Q` to a linear unit correctly;
// mostly useful for velocities
template <isQuantity Q> Quantity<typename Q::mass, typename Q::angle, typename Q::time, typename Q::current,
typename Q::length, typename Q::temperature, typename Q::luminosity, typename Q::moles>
toLinear(Quantity<typename Q::mass, typename Q::length, typename Q::time, typename Q::current, typename Q::angle,
typename Q::temperature, typename Q::luminosity, typename Q::moles>
angular,
Length diameter) {
template <isQuantity Q>
Quantity<typename Q::mass, typename Q::angle, typename Q::time, typename Q::current, typename Q::length,
typename Q::temperature, typename Q::luminosity,
typename Q::moles> constexpr toLinear(Quantity<typename Q::mass, typename Q::length, typename Q::time,
typename Q::current, typename Q::angle, typename Q::temperature,
typename Q::luminosity, typename Q::moles>
angular,
Length diameter) {
return unit_cast<Quantity<typename Q::mass, typename Q::angle, typename Q::time, typename Q::current,
typename Q::length, typename Q::temperature, typename Q::luminosity, typename Q::moles>>(
angular * (diameter / 2.0));
}

// Convert an linear unit `Q` to a angular unit correctly;
// mostly useful for velocities
template <isQuantity Q> Quantity<typename Q::mass, typename Q::angle, typename Q::time, typename Q::current,
typename Q::length, typename Q::temperature, typename Q::luminosity, typename Q::moles>
toAngular(Quantity<typename Q::mass, typename Q::length, typename Q::time, typename Q::current, typename Q::angle,
typename Q::temperature, typename Q::luminosity, typename Q::moles>
linear,
Length diameter) {
template <isQuantity Q>
Quantity<typename Q::mass, typename Q::angle, typename Q::time, typename Q::current, typename Q::length,
typename Q::temperature, typename Q::luminosity,
typename Q::moles> constexpr toAngular(Quantity<typename Q::mass, typename Q::length, typename Q::time,
typename Q::current, typename Q::angle,
typename Q::temperature, typename Q::luminosity,
typename Q::moles>
linear,
Length diameter) {
return unit_cast<Quantity<typename Q::mass, typename Q::angle, typename Q::time, typename Q::current,
typename Q::length, typename Q::temperature, typename Q::luminosity, typename Q::moles>>(
linear / (diameter / 2.0));
Expand Down
25 changes: 17 additions & 8 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

constexpr int r2i(double value) { return static_cast<int>(value >= 0.0 ? value + 0.5 : value - 0.5); }

/**
* Runs initialization code. This occurs as soon as the program is started.
*
* All other competition modes are blocked by initialize; it is recommended
* to keep execution time for this mode under a few seconds.
*/
void initialize() {
std::cout << std::format("{:.2f}", 15.2_cm) << std::endl; // should output 0.15_m
std::cout << std::format("{:.2f}", 180_stDeg) << std::endl; // should output 3.14_stRad
std::cout << std::format("{:.2f}", 0_celsius) << std::endl; // should output 273.15
std::cout << std::format("{:.2f}", 1.2345) << std::endl;
}

constexpr void miscTests() {
units::AccelerationPose a(1_mps2, 2_mps2);
Number num = Number(1.0);
num = Number(0.0);
Expand All @@ -30,12 +31,18 @@ void initialize() {
std::ratio<0>, std::ratio<0>, std::ratio<0>>(5.0));
units::max(10_celsius, Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>,
std::ratio<1>, std::ratio<0>, std::ratio<0>>(1.0));
}

constexpr void v3dTests() {
// check Vector3D overloads
units::Vector3D<Length> v3a = 2 * units::V3Position(2_in, 2_in, 2_in) * 2;
units::Vector3D<Length> v3b = units::V3Position(2_in, 2_in, 2_in) / 2.0;
units::Vector3D<Area> v3c = 2_in * units::V3Position(2_in, 2_in, 2_in);
units::Vector3D<Area> v3d = units::V3Position(2_in, 2_in, 2_in) * 2_in;
units::Vector3D<Number> v3e = units::V3Position(2_in, 2_in, 2_in) / 2_in;
}

constexpr void v2dTests() {
// check Vector2D overloads
units::Vector2D<Length> v2a = units::V2Position(2_in, 2_in) / 2;
units::Vector2D<Length> v2b = 2 * units::V2Position(2_in, 2_in) * 2;
Expand Down Expand Up @@ -81,12 +88,14 @@ constexpr double doubleAssignmentTests() {
return d;
}

void numberOperatorTests() {
constexpr void numberOperatorTests() {
using namespace units_double_ops;
static_assert(1_num + 2 == 3);
static_assert(1 + 2_num <= 3);
static_assert(1 / 2_num >= 0);

static_assert(numAssignmentTests() == 0);
static_assert(doubleAssignmentTests() == 1);
}
}

constexpr void formatTests() {}

0 comments on commit f802474

Please sign in to comment.