Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
quantity_kind.hpp
Go to the documentation of this file.
1// Copyright 2026, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_QUANTITY_KIND_HPP_
5#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_QUANTITY_KIND_HPP_
6
7#include "arene/base/constraints/constraints.hpp"
8#include "arene/base/stdlib_choice/declval.hpp"
9#include "arene/base/stdlib_choice/enable_if.hpp"
10#include "arene/base/stdlib_choice/is_class.hpp"
11#include "arene/base/stdlib_choice/is_same.hpp"
12#include "arene/base/stdlib_choice/remove_cv.hpp"
13#include "arene/base/type_traits/conditional.hpp"
14#include "arene/base/units/detail/missing.hpp"
15#include "arene/base/units/is_possible_unit_for.hpp"
16#include "arene/base/units/is_quantity_kind.hpp"
17#include "arene/base/units/is_unit.hpp"
18#include "arene/base/units/kind_with_exponent_fwd.hpp"
19#include "arene/base/units/quantity_origin.hpp"
20
21namespace arene {
22namespace base {
23
24namespace quantity_kind_detail {
25
26/// @brief Helper to check if @c Type is @c Missing
27template <typename Type>
28extern constexpr bool is_missing_v = std::is_same<Type, units_detail::missing>::value;
29
30/// @brief helper used to rebind the unit type of a quantity kind
31template <typename>
32auto rebind_quantity_kind_unit_type() -> void = delete;
33
34/// @brief Mixin base class for declaring the unit of a quantity kind
35/// @tparam Unit the type of the default unit for the quantity kind
36template <typename Unit>
37class quantity_kind_unit_mixin {
38 public:
39 /// @brief Type alias to specify the unit for this quantity kind
40 using unit_type = Unit;
41};
42
43/// @brief Mixin base class for declaring the unit of a quantity kind
44template <>
45class quantity_kind_unit_mixin<units_detail::missing> {};
46
47/// @brief Mixin base class for declaring the origin of a quantity kind
48/// @tparam Origin the type of the origin for the quantity kind
49template <typename Origin>
50class quantity_kind_origin_mixin {
51 public:
52 /// @brief Type alias to specify the origin for this quantity kind
53 using origin = Origin;
54};
55
56/// @brief Mixin base class for declaring the origin of a quantity kind
57template <>
58class quantity_kind_origin_mixin<units_detail::missing> {};
59
60/// @brief Mixin base class for declaring a parent quantity kind for a derived quantity kind
61/// @tparam ParentKind the type of the parent quantity kind for the derived quantity kind
62template <typename ParentKind>
63class quantity_kind_parent_mixin {
64 public:
65 /// @brief Type alias for the parent quantity kind
66 using parent_quantity_kind_type = ParentKind;
67};
68
69/// @brief Mixin base class for declaring a parent quantity kind for a derived quantity kind
70/// @tparam ParentKind the type of the parent quantity kind for the derived quantity kind
71template <>
72class quantity_kind_parent_mixin<units_detail::missing> {};
73
74/// @brief Base class for declaring a quantity kind
75/// @tparam Derived the derived class which represents the quantity kind
76/// @tparam OptionalParentKind the type of the parent quantity kind for @c Derived if there is one, otherwise @c missing
77/// @tparam OptionalOrigin the type of the quantity origin for @c Derived if there is one, otherwise @c missing
78/// @tparam OptionalUnit the type of the default unit for @c Derived if there is one, otherwise @c missing
79template <typename Derived, typename OptionalParentKind, typename OptionalOrigin, typename OptionalUnit>
80class quantity_kind_base
81 : public quantity_kind_parent_mixin<OptionalParentKind>
82 , public quantity_kind_origin_mixin<OptionalOrigin>
83 , public quantity_kind_unit_mixin<OptionalUnit> {
84 public:
85 /// @brief Type alias to facilitate detecting quantity kinds
86 using quantity_kind_type = Derived;
87
88 /// @brief Alias for a quantity kind which is the quantity kind @c Derived with the specified @c Exponent
89 /// @tparam Exponent The exponent to use
90 template <units_detail::exponent_t Exponent>
91 using with_exponent = kind_with_exponent_t<Derived, Exponent>;
92
93 /// @brief Alias for a quantity kind with @c Derived as the parent kind and a specified unit
94 /// @tparam OtherUnit selected unit for quantity kind
95 template <typename OtherUnit>
96 using in = std::enable_if_t<
97 std::is_class<OtherUnit>::value,
98 decltype(rebind_quantity_kind_unit_type(std::declval<quantity_kind_base>(), std::declval<OtherUnit>()))>;
99};
100
101/// @brief Class to hold a bunch of reusable sanity checks for the specializations of @c choose_quantity_kind_base
102/// @tparam Derived the user-supplied derived type attempting to inherit from the @c quantity_kind class
103/// @tparam OptionalParentKind the parent kind chosen by @c choose_quantity_kind_base or @c missing if none
104/// @tparam OptionalOrigin the origin chosen by @c choose_quantity_kind_base or @c missing if none
105/// @tparam OptionalUnit the unit chosen by @c choose_quantity_kind_base or @c missing if none
106template <typename Derived, typename OptionalParentKind, typename OptionalOrigin, typename OptionalUnit>
107class choose_quantity_kind_sanity_check {
108 static_assert(
109 is_missing_v<OptionalParentKind> || is_quantity_kind_v<OptionalParentKind>,
110 "The specified parent kind must be a quantity kind"
111 );
112 static_assert(
113 is_missing_v<OptionalParentKind> || !is_unit_v<OptionalParentKind>,
114 "The specified parent kind must not be a unit"
115 );
116
117 static_assert(
118 is_missing_v<OptionalOrigin> || is_quantity_origin_v<OptionalOrigin>,
119 "The specified origin must be a quantity origin"
120 );
121
122 static_assert(is_missing_v<OptionalUnit> || is_unit_v<OptionalUnit>, "The specified unit must be a quantity unit");
123 static_assert(
124 is_missing_v<OptionalUnit> || units_detail::is_declared_possible_unit_for_v<OptionalUnit, Derived> ||
125 is_possible_unit_for_v<OptionalUnit, OptionalParentKind>,
126 "The specified unit must be a possible unit for the specified kind or for its parent kind"
127 );
128};
129
130/// @brief Get the origin that should be used for a derived quantity kind with a given parent and requested origin
131/// @tparam MaybeParentKind either the parent kind of the derived quantity kind, or @c missing
132/// @tparam MaybeDerivedOrigin either the requested origin of the derived quantity kind, or @c missing
133template <typename MaybeParentKind, typename MaybeDerivedOrigin, typename = constraints<>>
134class derived_origin_impl {
135 public:
136 /// @brief When the parent kind has no origin and no origin was requested, the derived kind has no origin
137 using type = units_detail::missing;
138};
139
140/// @brief Get the origin that should be used for a derived quantity kind with a given parent and requested origin
141/// @tparam MaybeParentKind either the parent kind of the derived quantity kind, or @c missing
142/// @tparam MaybeDerivedOrigin either the requested origin of the derived quantity kind, or @c missing
143template <typename MaybeParentKind>
144class derived_origin_impl<
145 MaybeParentKind,
146 units_detail::missing,
147 constraints<std::enable_if_t<quantity_has_origin_v<MaybeParentKind>>>> {
148 public:
149 /// @brief When the parent kind has an origin and no origin was requested, the derived kind has the parent's origin
150 using type = typename MaybeParentKind::origin;
151};
152
153/// @brief Get the origin that should be used for a derived quantity kind with a given parent and requested origin
154/// @tparam MaybeParentKind either the parent kind of the derived quantity kind, or @c missing
155/// @tparam MaybeDerivedOrigin either the requested origin of the derived quantity kind, or @c missing
156template <typename MaybeParentKind, typename MaybeDerivedOrigin>
157class derived_origin_impl<
158 MaybeParentKind,
159 MaybeDerivedOrigin,
160 constraints<std::enable_if_t<!quantity_has_origin_v<MaybeParentKind>>>> {
161 public:
162 /// @brief When the parent kind has no origin and an origin was requested, the derived kind has the requested origin
163 using type = MaybeDerivedOrigin;
164};
165
166/// @brief Get the origin that should be used for a derived quantity kind with a given parent and requested origin
167/// @tparam MaybeParentKind either the parent kind of the derived quantity kind, or @c missing
168/// @tparam MaybeDerivedOrigin either the requested origin of the derived quantity kind, or @c missing
169template <typename MaybeParentKind, typename MaybeDerivedOrigin>
170class derived_origin_impl<
171 MaybeParentKind,
172 MaybeDerivedOrigin,
173 constraints<std::enable_if_t<quantity_has_origin_v<MaybeParentKind>>>> {
174 static_assert(
175 quantity_origin_detail::origin_is_relative_to_v<MaybeDerivedOrigin, typename MaybeParentKind::origin>,
176 "If the parent of a derived quantity kind has an origin, the derived kind's origin must be relative to it"
177 );
178
179 public:
180 /// @brief When the parent kind has an origin and an origin was requested, the derived kind has the requested origin
181 using type = MaybeDerivedOrigin;
182};
183
184/// @brief Get the origin that should be used for a derived quantity kind with a given parent and requested origin
185/// @tparam MaybeParentKind either the parent kind of the derived quantity kind, or @c missing
186/// @tparam MaybeDerivedOrigin either the requested origin of the derived quantity kind, or @c missing
187template <typename MaybeParentKind, typename MaybeDerivedOrigin>
188using derived_origin_t = typename derived_origin_impl<MaybeParentKind, MaybeDerivedOrigin>::type;
189
190/// @brief Helper class to choose the base class for defining a quantity_kind based on the provided template parameters
191/// @tparam Derived the derived class which represents the quantity kind
192/// @tparam ParentKindOrOriginOrUnit the type of the parent quantity kind, origin, or default unit for <c>Derived</c>,
193/// if any
194/// @tparam OriginOrUnit the type of the origin or default unit for <c>Derived</c>, if any
195/// @tparam Unit the type of the default unit for <c>Derived</c>, if any
196/// @note This is the base specialization, chosen when all three optional parameters are present (not <c>missing</c>)
197template <typename Derived, typename ParentKindOrOriginOrUnit, typename OriginOrUnit, typename Unit>
198class choose_quantity_kind_base {
199 /// @brief In the base case where all parameters are present, the parent is the first optional parameter
200 using actual_parent = ParentKindOrOriginOrUnit;
201
202 /// @brief In the base case where all parameters are present, the origin is the second optional parameter
203 using actual_origin = OriginOrUnit;
204
205 /// @brief In the base case where all parameters are present, the unit is the third optional parameter
206 using actual_unit = Unit;
207
208 // parasoft-begin-suppress AUTOSAR-M0_1_3-c "This sanity check variable is 'used' simply by instantiating it"
209 /// @brief Instantiate the sanity check struct that does some static assertions on the arguments
210 static constexpr choose_quantity_kind_sanity_check<Derived, actual_parent, actual_origin, actual_unit> check{};
211 // parasoft-end-suppress AUTOSAR-M0_1_3-c
212
213 public:
214 /// @brief A type alias for the base class to use
215 using type = quantity_kind_base<Derived, actual_parent, derived_origin_t<actual_parent, actual_origin>, actual_unit>;
216};
217
218/// @brief Helper class to choose the base class for defining a quantity_kind based on the provided template parameters
219/// @tparam Derived the derived class which represents the quantity kind
220/// @tparam ParentKindOrOriginOrUnit the type of the parent quantity kind, origin, or default unit for <c>Derived</c>,
221/// if any
222/// @tparam OriginOrUnit the type of the origin or default unit for <c>Derived</c>, if any
223/// @tparam Unit the type of the default unit for <c>Derived</c>, if any
224/// @note This is the two-argument specialization, chosen when two optional parameters are present (not <c>missing</c>)
225template <typename Derived, typename ParentKindOrOrigin, typename OriginOrUnit>
226class choose_quantity_kind_base<Derived, ParentKindOrOrigin, OriginOrUnit, units_detail::missing> {
227 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: 'missing' does not hide anything"
228 /// @brief Type alias for @c missing because it's used several times
229 using missing = units_detail::missing;
230 // parasoft-end-suppress AUTOSAR-A2_10_1-
231
232 /// @brief The actual parent kind specified for this quantity kind, or @c missing if there is none
233 using actual_parent = conditional_t<!is_quantity_origin_v<ParentKindOrOrigin>, ParentKindOrOrigin, missing>;
234
235 /// @brief The actual origin specified for this quantity kind, or @c missing if there is none
236 using actual_origin = conditional_t<
237 !is_quantity_kind_v<ParentKindOrOrigin>,
238 ParentKindOrOrigin,
239 conditional_t<!is_unit_v<OriginOrUnit>, OriginOrUnit, missing>>;
240
241 /// @brief The actual unit type specified for this quantity kind, or @c missing if there is none
242 using actual_unit = conditional_t<!is_quantity_origin_v<OriginOrUnit>, OriginOrUnit, missing>;
243
244 // parasoft-begin-suppress AUTOSAR-M0_1_3-c "This sanity check variable is 'used' simply by instantiating it"
245 /// @brief Instantiate the sanity check struct that does some static assertions on the arguments
246 static constexpr choose_quantity_kind_sanity_check<Derived, actual_parent, actual_origin, actual_unit> check{};
247 // parasoft-end-suppress AUTOSAR-M0_1_3-c
248
249 public:
250 /// @brief A type alias for the base class to use
251 using type = quantity_kind_base<Derived, actual_parent, derived_origin_t<actual_parent, actual_origin>, actual_unit>;
252};
253
254/// @brief Helper class to choose the base class for defining a quantity_kind based on the provided template parameters
255/// @tparam Derived the derived class which represents the quantity kind
256/// @tparam ParentKindOrOriginOrUnit the type of the parent quantity kind, origin, or default unit for <c>Derived</c>,
257/// if any
258/// @tparam OriginOrUnit the type of the origin or default unit for <c>Derived</c>, if any
259/// @tparam Unit the type of the default unit for <c>Derived</c>, if any
260/// @note This is the one-argument specialization, chosen when one optional parameter is present (not <c>missing</c>)
261template <typename Derived, typename ParentKindOrOriginOrUnit>
262class choose_quantity_kind_base<Derived, ParentKindOrOriginOrUnit, units_detail::missing, units_detail::missing> {
263 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: 'missing' does not hide anything"
264 /// @brief Type alias for @c missing because it's used several times
265 using missing = units_detail::missing;
266 // parasoft-end-suppress AUTOSAR-A2_10_1-d
267
268 /// @brief The actual parent kind specified for this quantity kind, or @c missing if there is none
269 using actual_parent = conditional_t<
270 !is_quantity_origin_v<ParentKindOrOriginOrUnit> && !is_unit_v<ParentKindOrOriginOrUnit>,
271 ParentKindOrOriginOrUnit,
272 missing>;
273
274 /// @brief The actual origin specified for this quantity kind, or @c missing if there is none
275 using actual_origin =
276 conditional_t<is_quantity_origin_v<ParentKindOrOriginOrUnit>, ParentKindOrOriginOrUnit, missing>;
277
278 /// @brief The actual unit type specified for this quantity kind, or @c missing if there is none
279 using actual_unit = conditional_t<is_unit_v<ParentKindOrOriginOrUnit>, ParentKindOrOriginOrUnit, missing>;
280
281 // parasoft-begin-suppress AUTOSAR-M0_1_3-c "This sanity check variable is 'used' simply by instantiating it"
282 /// @brief Instantiate the sanity check struct that does some static assertions on the arguments
283 static constexpr choose_quantity_kind_sanity_check<Derived, actual_parent, actual_origin, actual_unit> check{};
284 // parasoft-end-suppress AUTOSAR-M0_1_3-c
285
286 public:
287 /// @brief A type alias for the base class to use
288 using type = quantity_kind_base<Derived, actual_parent, derived_origin_t<actual_parent, actual_origin>, actual_unit>;
289};
290
291/// @brief Helper class to choose the base class for defining a quantity_kind based on the provided template parameters
292/// @tparam Derived the derived class which represents the quantity kind
293/// @tparam ParentKindOrOriginOrUnit the type of the parent quantity kind, origin, or default unit for <c>Derived</c>,
294/// if any
295/// @tparam OriginOrUnit the type of the origin or default unit for <c>Derived</c>, if any
296/// @tparam Unit the type of the default unit for <c>Derived</c>, if any
297/// @note This is the zero-argument specialization, chosen when all optional parameters are set to @c missing
298template <typename Derived>
299class choose_quantity_kind_base<Derived, units_detail::missing, units_detail::missing, units_detail::missing> {
300 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False positive: 'missing' does not hide anything"
301 /// @brief Type alias for @c missing because it's used several times
302 using missing = units_detail::missing;
303 // parasoft-end-suppress AUTOSAR-A2_10_1-d
304
305 public:
306 /// @brief A type alias for the base class to use
307 using type = quantity_kind_base<Derived, missing, missing, missing>;
308};
309
310} // namespace quantity_kind_detail
311
312/// @brief ParentKind class for declaring a quantity kind with a parent quantity kind
313/// @tparam Derived the derived class which represents the quantity kind
314/// @tparam ParentKindOrOriginOrUnit optional; the type of the parent quantity kind for @c Derived, or the type of the
315/// quantity origin, or the type of the default unit
316/// @tparam OriginOrUnit optional; the type of the quantity origin, or the default unit. Must not be specified if
317/// @c ParentKindOrOriginOrUnit is a unit, and must not be an origin if @c ParentKindOrOriginOrUnit is an origin
318/// @tparam Unit the type of the default unit. Must not be specified if either of @c ParentKindOrOriginOrUnit or
319/// @c OriginOrUnit is a unit
320///
321/// @pre @c Derived must derive from @c quantity_kind<Derived, ParentKindOrUnit, Unit>
322template <
323 typename Derived,
326 typename Unit = units_detail::missing>
328 Derived,
332
333} // namespace base
334} // namespace arene
335
336#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_QUANTITY_KIND_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10