WPILibC++ 2023.4.3
Units.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <fmt/format.h>
8
9#include "units/base.h"
10
11/**
12 * Formatter for unit types.
13 *
14 * @tparam Units Unit tag for which type of units the `unit_t` represents (e.g.
15 * meters).
16 * @tparam T Underlying type of the storage. Defaults to double.
17 * @tparam NonLinearScale Optional scale class for the units. Defaults to linear
18 * (i.e. does not scale the unit value). Examples of
19 * non-linear scales could be logarithmic, decibel, or
20 * richter scales. Non-linear scales must adhere to the
21 * non-linear-scale concept.
22 */
23template <class Units, typename T, template <typename> class NonLinearScale>
24struct fmt::formatter<units::unit_t<Units, T, NonLinearScale>>
25 : fmt::formatter<double> {
26 /**
27 * Writes out a formatted unit.
28 *
29 * @tparam FormatContext Format string context type.
30 * @param obj Unit instance.
31 * @param ctx Format string context.
32 */
33 template <typename FormatContext>
35 FormatContext& ctx) {
36 using BaseUnits =
38 typename units::traits::unit_traits<Units>::base_unit_type>;
39
40 auto out = ctx.out();
41
43 units::convert<Units, BaseUnits>(obj()), ctx);
44
45 if constexpr (units::traits::unit_traits<
46 Units>::base_unit_type::meter_ratio::num != 0) {
47 out = fmt::format_to(out, " m");
48 }
49 if constexpr (units::traits::unit_traits<
50 Units>::base_unit_type::meter_ratio::num != 0 &&
51 units::traits::unit_traits<
52 Units>::base_unit_type::meter_ratio::num != 1) {
53 out = fmt::format_to(
54 out, "^{}",
55 units::traits::unit_traits<Units>::base_unit_type::meter_ratio::num);
56 }
57 if constexpr (units::traits::unit_traits<
58 Units>::base_unit_type::meter_ratio::den != 1) {
59 out = fmt::format_to(
60 out, "/{}",
61 units::traits::unit_traits<Units>::base_unit_type::meter_ratio::den);
62 }
63
64 if constexpr (units::traits::unit_traits<
65 Units>::base_unit_type::kilogram_ratio::num != 0) {
66 out = fmt::format_to(out, " kg");
67 }
68 if constexpr (units::traits::unit_traits<
69 Units>::base_unit_type::kilogram_ratio::num != 0 &&
70 units::traits::unit_traits<
71 Units>::base_unit_type::kilogram_ratio::num != 1) {
72 out = fmt::format_to(out, "^{}",
73 units::traits::unit_traits<
74 Units>::base_unit_type::kilogram_ratio::num);
75 }
76 if constexpr (units::traits::unit_traits<
77 Units>::base_unit_type::kilogram_ratio::den != 1) {
78 out = fmt::format_to(out, "/{}",
79 units::traits::unit_traits<
80 Units>::base_unit_type::kilogram_ratio::den);
81 }
82
83 if constexpr (units::traits::unit_traits<
84 Units>::base_unit_type::second_ratio::num != 0) {
85 out = fmt::format_to(out, " s");
86 }
87 if constexpr (units::traits::unit_traits<
88 Units>::base_unit_type::second_ratio::num != 0 &&
89 units::traits::unit_traits<
90 Units>::base_unit_type::second_ratio::num != 1) {
91 out = fmt::format_to(
92 out, "^{}",
93 units::traits::unit_traits<Units>::base_unit_type::second_ratio::num);
94 }
95 if constexpr (units::traits::unit_traits<
96 Units>::base_unit_type::second_ratio::den != 1) {
97 out = fmt::format_to(
98 out, "/{}",
99 units::traits::unit_traits<Units>::base_unit_type::second_ratio::den);
100 }
101
102 if constexpr (units::traits::unit_traits<
103 Units>::base_unit_type::ampere_ratio::num != 0) {
104 out = fmt::format_to(out, " A");
105 }
106 if constexpr (units::traits::unit_traits<
107 Units>::base_unit_type::ampere_ratio::num != 0 &&
108 units::traits::unit_traits<
109 Units>::base_unit_type::ampere_ratio::num != 1) {
110 out = fmt::format_to(
111 out, "^{}",
112 units::traits::unit_traits<Units>::base_unit_type::ampere_ratio::num);
113 }
114 if constexpr (units::traits::unit_traits<
115 Units>::base_unit_type::ampere_ratio::den != 1) {
116 out = fmt::format_to(
117 out, "/{}",
118 units::traits::unit_traits<Units>::base_unit_type::ampere_ratio::den);
119 }
120
121 if constexpr (units::traits::unit_traits<
122 Units>::base_unit_type::kelvin_ratio::num != 0) {
123 out = fmt::format_to(out, " K");
124 }
125 if constexpr (units::traits::unit_traits<
126 Units>::base_unit_type::kelvin_ratio::num != 0 &&
127 units::traits::unit_traits<
128 Units>::base_unit_type::kelvin_ratio::num != 1) {
129 out = fmt::format_to(
130 out, "^{}",
131 units::traits::unit_traits<Units>::base_unit_type::kelvin_ratio::num);
132 }
133 if constexpr (units::traits::unit_traits<
134 Units>::base_unit_type::kelvin_ratio::den != 1) {
135 out = fmt::format_to(
136 out, "/{}",
137 units::traits::unit_traits<Units>::base_unit_type::kelvin_ratio::den);
138 }
139
140 if constexpr (units::traits::unit_traits<
141 Units>::base_unit_type::mole_ratio::num != 0) {
142 out = fmt::format_to(out, " mol");
143 }
144 if constexpr (units::traits::unit_traits<
145 Units>::base_unit_type::mole_ratio::num != 0 &&
146 units::traits::unit_traits<
147 Units>::base_unit_type::mole_ratio::num != 1) {
148 out = fmt::format_to(
149 out, "^{}",
150 units::traits::unit_traits<Units>::base_unit_type::mole_ratio::num);
151 }
152 if constexpr (units::traits::unit_traits<
153 Units>::base_unit_type::mole_ratio::den != 1) {
154 out = fmt::format_to(
155 out, "/{}",
156 units::traits::unit_traits<Units>::base_unit_type::mole_ratio::den);
157 }
158
159 if constexpr (units::traits::unit_traits<
160 Units>::base_unit_type::candela_ratio::num != 0) {
161 out = fmt::format_to(out, " cd");
162 }
163 if constexpr (units::traits::unit_traits<
164 Units>::base_unit_type::candela_ratio::num != 0 &&
165 units::traits::unit_traits<
166 Units>::base_unit_type::candela_ratio::num != 1) {
167 out = fmt::format_to(out, "^{}",
168 units::traits::unit_traits<
169 Units>::base_unit_type::candela_ratio::num);
170 }
171 if constexpr (units::traits::unit_traits<
172 Units>::base_unit_type::candela_ratio::den != 1) {
173 out = fmt::format_to(out, "/{}",
174 units::traits::unit_traits<
175 Units>::base_unit_type::candela_ratio::den);
176 }
177
178 if constexpr (units::traits::unit_traits<
179 Units>::base_unit_type::radian_ratio::num != 0) {
180 out = fmt::format_to(out, " rad");
181 }
182 if constexpr (units::traits::unit_traits<
183 Units>::base_unit_type::radian_ratio::num != 0 &&
184 units::traits::unit_traits<
185 Units>::base_unit_type::radian_ratio::num != 1) {
186 out = fmt::format_to(
187 out, "^{}",
188 units::traits::unit_traits<Units>::base_unit_type::radian_ratio::num);
189 }
190 if constexpr (units::traits::unit_traits<
191 Units>::base_unit_type::radian_ratio::den != 1) {
192 out = fmt::format_to(
193 out, "/{}",
194 units::traits::unit_traits<Units>::base_unit_type::radian_ratio::den);
195 }
196
197 if constexpr (units::traits::unit_traits<
198 Units>::base_unit_type::byte_ratio::num != 0) {
199 out = fmt::format_to(out, " b");
200 }
201 if constexpr (units::traits::unit_traits<
202 Units>::base_unit_type::byte_ratio::num != 0 &&
203 units::traits::unit_traits<
204 Units>::base_unit_type::byte_ratio::num != 1) {
205 out = fmt::format_to(
206 out, "^{}",
207 units::traits::unit_traits<Units>::base_unit_type::byte_ratio::num);
208 }
209 if constexpr (units::traits::unit_traits<
210 Units>::base_unit_type::byte_ratio::den != 1) {
211 out = fmt::format_to(
212 out, "/{}",
213 units::traits::unit_traits<Units>::base_unit_type::byte_ratio::den);
214 }
215
216 return out;
217 }
218};
Container for values which represent quantities of a given unit.
Definition: base.h:1926
Unit Conversion Library namespace.
Definition: current.h:31
auto format(const units::unit_t< Units, T, NonLinearScale > &obj, FormatContext &ctx)
Writes out a formatted unit.
Definition: Units.h:34
Type representing an arbitrary unit.
Definition: base.h:884
auto format(wformat_string< T... > fmt, T &&... args) -> std::wstring
Definition: xchar.h:87
auto format_to(OutputIt out, const S &fmt, Args &&... args) -> OutputIt
Definition: xchar.h:136