Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
base_kind_set.hpp
Go to the documentation of this file.
1#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_BASE_KIND_SET_HPP_
2#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_BASE_KIND_SET_HPP_
3
4#include "arene/base/algorithm/transform.hpp"
5#include "arene/base/array/array.hpp"
6#include "arene/base/contracts/contract.hpp"
7#include "arene/base/functional/bind_front.hpp"
8#include "arene/base/stdlib_choice/multiplies.hpp"
9#include "arene/base/stdlib_choice/remove_const.hpp"
10#include "arene/base/type_list/concat_unique.hpp"
11#include "arene/base/type_list/index_of.hpp"
12#include "arene/base/type_list/type_list.hpp"
13#include "arene/base/type_manipulation/consume_values.hpp"
14#include "arene/base/type_traits/all_of.hpp"
15#include "arene/base/type_traits/is_instantiation_of.hpp"
16#include "arene/base/units/is_quantity_kind.hpp"
17#include "arene/base/units/kind_with_exponent_fwd.hpp"
18
19// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
20// parasoft-begin-suppress AUTOSAR-M2_10_1-a "Similar identifiers permitted by M2-10-1 Permit #1 v1.0.0"
21// parasoft-begin-suppress AUTOSAR-A3_1_5-a "False positive: all functions are constexpr so are intended to be inlined"
22// parasoft-begin-suppress CERT_C-EXP37-a "False positive: The rule does not mention naming all parameters"
23
24namespace arene {
25namespace base {
26namespace units_detail {
27
28/// @brief specifies the exponents of a quantity kind in the base kind set
29class base_kind_exponents {
30 /// @brief positive exponent value
31 exponent_t positive_;
32 /// @brief negative exponent value
33 exponent_t negative_;
34
35 public:
36 /// @brief constuct with the provided exponents
37 /// @param pos positive exponent value
38 /// @param neg negative exponent value
39 /// @pre @c pos is non-negative
40 /// @pre @c neg is non-negative
41 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
42 constexpr base_kind_exponents(exponent_t pos, exponent_t neg) noexcept
43 : positive_{pos},
44 negative_{neg} {
45 ARENE_PRECONDITION(pos >= 0);
46 ARENE_PRECONDITION(neg >= 0);
47 }
48
49 /// @brief default constuct with zero for both positive and negative exponents
50 constexpr base_kind_exponents() noexcept
51 : base_kind_exponents{0, 0} {}
52
53 /// @brief obtain the positive exponent value
54 /// @return positive exponent value
55 constexpr auto positive() const noexcept -> exponent_t { return positive_; }
56
57 /// @brief obtain the negative exponent value
58 /// @return negative exponent value
59 constexpr auto negative() const noexcept -> exponent_t { return negative_; }
60
61 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
62 /// @brief scale exponents by a scaling factor
63 /// @param scaling factor to scale exponents by
64 /// @param self positive and negative exponents
65 /// @return exponents after applying @c scaling
66 /// @note This function does not guard against overflow/underflow as it is
67 /// should only be invoked in a constant expression.
68 friend constexpr auto operator*(exponent_t const scaling, base_kind_exponents const self) noexcept
69 -> base_kind_exponents {
70 if (scaling < 0) {
71 return {-scaling * self.negative(), -scaling * self.positive()};
72 }
73
74 return {scaling * self.positive(), scaling * self.negative()};
75 }
76 // parasoft-end-suppress AUTOSAR-A11_3_1-a
77
78 /// @brief combine exponents
79 /// @param other exponents to add to @c *this
80 /// @return @c *this
81 /// @note This function does not guard against overflow/underflow as it is
82 /// should only be invoked in a constant expression.
83 // parasoft-begin-suppress AUTOSAR-A7_1_3-a "False positive: const is placed on the right hand side"
84 constexpr auto operator+=(base_kind_exponents const other) noexcept -> base_kind_exponents& {
85 positive_ += other.positive();
86 negative_ += other.negative();
87 return *this;
88 }
89 // parasoft-end-suppress AUTOSAR-A7_1_3-a
90};
91
92/// @brief specifies a set of base quantity kinds with associated exponents
93/// @tparam Kinds base quantity kind types
94template <typename... Kinds>
95class base_kind_set {
96 public:
97 static_assert(all_of_v<is_quantity_kind_v<Kinds>...>, "every type in 'Kinds' must be a quantity kind");
98
99 /// @brief exponents associated with each quantity kind base
100 ///
101 /// Exponent values are associated the quantity kind with the same index.
102 // parasoft-begin-suppress AUTOSAR-M11_0_1-a "'base_kind_set' is an implementation detail with no class invariants"
103 // parasoft-begin-suppress AUTOSAR-M8_5_2-a "False positive: correct initialization"
104 // parasoft-begin-suppress AUTOSAR-M8_5_2-b "False positive: correct initialization"
105 arene::base::array<base_kind_exponents, sizeof...(Kinds)> exponents{};
106 // parasoft-end-suppress AUTOSAR-M8_5_2-a
107 // parasoft-end-suppress AUTOSAR-M8_5_2-b
108 // parasoft-end-suppress AUTOSAR-M11_0_1-a
109
110 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2 v1.0.0"
111 // parasoft-begin-suppress AUTOSAR-A0_1_3-a "False positive: This is a
112 // public function, and doesn't need to be used in the translation unit"
113 /// @brief scale exponents by a scaling factor
114 /// @param scaling factor to scale exponents by
115 /// @param self set of base quantity kinds with associated exponents
116 /// @return base quantity kinds after scaling exponents values
117 friend constexpr auto operator*(exponent_t const scaling, base_kind_set const& self) noexcept -> base_kind_set {
118 auto updated = base_kind_set{};
119 arene::base::transform( //
120 self.exponents.begin(),
121 self.exponents.end(),
122 updated.exponents.begin(),
123 bind_front(std::multiplies<>{}, scaling)
124 );
125 return updated;
126 }
127 // parasoft-end-suppress AUTOSAR-A0_1_3-a
128 // parasoft-end-suppress AUTOSAR-A11_3_1-a
129
130 /// @brief obtain the exponent values for the specified quantity kind
131 /// @tparam Kind quantity kind of which to obtain the exponent values
132 /// @return reference to the exponents
133 /// @note error if @c Kind is not in @c Kinds...
134 template <typename Kind>
135 constexpr auto exponent_for() noexcept -> base_kind_exponents& {
136 return get<type_lists::index_of_v<base_kind_set, Kind>>(exponents);
137 }
138 /// @brief obtain the exponent values for the specified quantity kind
139 /// @tparam Kind quantity kind of which to obtain the exponent values
140 /// @return reference to the exponents
141 /// @note error if @c Kind is not in @c Kinds...
142 template <typename Kind>
143 constexpr auto exponent_for() const noexcept -> base_kind_exponents const& {
144 return get<type_lists::index_of_v<base_kind_set, Kind>>(exponents);
145 }
146
147 // parasoft-begin-suppress AUTOSAR-M3_3_2-a "False positive: inline function used in multiple translation units"
148 /// @brief update exponents values from another base kind set
149 /// @tparam OtherKinds base quantity kind types of the other base kind set
150 /// @param other base kind set to combine with @c *this
151 /// @note error if any type in @c OtherKinds is not in @c Kinds..., i.e. @c
152 /// other must be a subset of @c *this
153 /// @return @c *this
154 ///
155 /// Updates @c *this with the exponent values from @c other.
156 template <typename... OtherKinds>
157 constexpr auto add_exponents_from(base_kind_set<OtherKinds...> const& other) noexcept -> base_kind_set& {
158 // parasoft-begin-suppress AUTOSAR-M5_18_1-a "Comma operator avoids an expensive recursive iteration"
159 consume_values({(exponent_for<OtherKinds>() += other.template exponent_for<OtherKinds>(), true)...});
160 // parasoft-end-suppress AUTOSAR-M5_18_1-a
161 return *this;
162 }
163};
164// parasoft-end-suppress AUTOSAR-M3_3_2-a
165
166// parasoft-begin-suppress AUTOSAR-M3_3_2-a "False positive: inline function used in multiple translation units"
167/// @brief combine base kind sets
168/// @tparam Bases base kind set types
169/// @param bases base kind sets to combine
170/// @return an base kind set which is the combination of all input sets
171template <typename... Bases>
172constexpr auto set_union(Bases const&... bases) noexcept -> type_lists::concat_unique_t<Bases...> {
173 static_assert(
174 all_of_v<is_instantiation_of_v<Bases, base_kind_set>...>,
175 "every type in 'Bases' must be a base kind set"
176 );
177
178 auto combined = type_lists::concat_unique_t<Bases...>{};
179
180 // parasoft-begin-suppress AUTOSAR-M5_18_1-a "Comma operator avoids an expensive recursive iteration"
181 consume_values({(combined.add_exponents_from(bases), true)...});
182 // parasoft-end-suppress AUTOSAR-M5_18_1-a
183
184 return combined;
185}
186// parasoft-end-suppress AUTOSAR-M3_3_2-a
187
188/// @brief converts a base kind set constant into a list of quantity kind types with exponents
189/// @tparam BaseKindSetConstant type constant that provides a base kind set as a
190/// @c static @c constexpr member @c value
191template <typename BaseKindSetConstant>
192class as_list_of_kinds_with_exponents {
193 // parasoft-begin-suppress CERT_C-PRE31-c "False positive: static_assert is a compile-time assert and can have no
194 // side-effects"
195 static_assert(
196 is_instantiation_of_v<std::remove_const_t<decltype(BaseKindSetConstant::value)>, base_kind_set>,
197 "'BaseKindSetConstant::value' must be a 'base_kind_set'"
198 );
199 // parasoft-end-suppress CERT_C-PRE31-c
200
201 /// @brief lifts a base kind set into a type list
202 /// @tparam BaseKinds quantity base kind types
203 /// @return base kind set lifted into a type list
204 template <typename... BaseKinds>
205 static auto impl(base_kind_set<BaseKinds...>) -> type_list<quantity_kind_with_exponent<
206 BaseKinds,
207 BaseKindSetConstant::value.template exponent_for<BaseKinds>().positive(),
208 BaseKindSetConstant::value.template exponent_for<BaseKinds>().negative()>...>;
209
210 public:
211 /// @brief base kind set type lifted into a type list
212 using type = decltype(impl(BaseKindSetConstant::value));
213};
214
215/// @brief converts a base kind set constant into a list of quantity kind types with exponents
216/// @tparam BaseKindSetConstant type constant that provides a base kind set as a
217/// @c static @c constexpr member @c value
218///
219/// Lifts the base kind set value specified by @c BaseKindSetConstant::value into a type.
220template <typename BaseKindSetConstant>
221using as_list_of_kinds_with_exponents_t = typename as_list_of_kinds_with_exponents<BaseKindSetConstant>::type;
222
223} // namespace units_detail
224} // namespace base
225} // namespace arene
226
227#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UNITS_BASE_KIND_SET_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10