1+ #include " ConstexprAlgorithms.hpp"
12
23namespace UnitGuard
34{
@@ -12,7 +13,7 @@ struct Power
1213 using base_type = Base;
1314 static constexpr int exponent = Exp;
1415
15- static_assert ( std::is_base_of< BaseUnit , Base >::value, " Power: Base must inherit from AtomTag" );
16+ static_assert ( std::is_base_of< AtomTag , Base >::value, " Power: Base must inherit from AtomTag" );
1617};
1718
1819// all Units we enforce compile-time constraints on are instantiations of "Unit", even non-composite units
@@ -34,38 +35,43 @@ struct Negate< Unit< Ps... > >
3435
3536// Merge.hpp -----------------------------------------------------------------------------
3637
37- // Forward declaration for internal helper that merges a single Power<B,E> into a Unit< Power<B_i, E_i>... >
38- template < typename UnitT, typename Pow >
39- struct MergePow ;
38+ template < typename UnsortedUnit, typename Head >
39+ using PrependUnit = Prepend< Unit, UnsortedUnit, Head >;
4040
41- // MergePow when the Unit is empty -> just place the new Power
41+ template < typename UnitInstance, typename Pow >
42+ struct MergeUnits ;
43+
44+ // 1) Base case, the base unit was not already present in the `Unit`s pack
4245template < typename Pow >
43- struct MergePow < Unit< >, Pow >
46+ struct MergeUnits < Unit< >, Pow >
4447{
4548 using type = Unit< Pow >;
4649};
4750
48- // MergePow when the first element has the same base -> add exponents
51+ // 2) When the first element shares the same base unit -> sum their exponents
4952template < typename Base, int E1 , int E2 , typename ... Rest >
50- struct MergePow < Unit< Power< Base, E1 >, Rest... >, Power< Base, E2 > >
53+ struct MergeUnits < Unit< Power< Base, E1 >, Rest... >, Power< Base, E2 > >
5154{
5255private:
5356 static constexpr int newExp = E1 + E2 ;
54- // If the sum is zero, we drop that base unit from the list
55- using merged_tail = std::conditional_t < newExp == 0 , Unit< Rest... >, Unit< Power< Base, newExp >, Rest... > >;
57+ // If the sum is zero, remove that base unit entirely
58+ using merged_tail = std::conditional_t <
59+ newExp == 0 ,
60+ Unit< Rest... >,
61+ Unit< Power< Base, newExp >, Rest... >
62+ >;
5663public:
5764 using type = merged_tail;
5865};
5966
60- // MergePow when the first element has a different base -> keep going
67+ // 3) When the first element doesn't share the same base unit -> keep the head, recurse on the tail
6168template < typename FirstPow, typename Pow, typename ... Rest >
62- struct MergePow < Unit< FirstPow, Rest... >, Pow >
69+ struct MergeUnits < Unit< FirstPow, Rest... >, Pow >
6370{
6471private:
65- using submerge = typename MergePow < Unit< Rest... >, Pow >::type;
72+ using submerge = typename MergeUnits < Unit< Rest... >, Pow >::type;
6673public:
67- // Reinsert `FirstPow` at the front
68- using type = Unit< FirstPow, typename submerge::Powers... >;
74+ using type = typename PrependUnit< submerge, FirstPow >::type;
6975};
7076
7177// -----------------------------------------------------------------------------
@@ -82,11 +88,11 @@ struct AddPack< U1, Unit< > >
8288};
8389
8490// Recursively add each Power from second to the first
85- template < typename U1 , typename Pow, typename ... Tail >
86- struct AddPack < U1 , Unit< Pow, Tail... > >
91+ template < typename P1 , typename Pow, typename ... Tail >
92+ struct AddPack < P1 , Unit< Pow, Tail... > >
8793{
8894private:
89- using merged = typename MergePow< U1 , Pow >::type;
95+ using merged = typename MergeUnits< P1 , Pow >::type;
9096public:
9197 using type = typename AddPack< merged, Unit< Tail... > >::type;
9298};
@@ -111,85 +117,29 @@ struct SubPack< U1, Unit< Pow, Tail... > >
111117private:
112118 // Subtracting Power<Base, E> is the same as adding Power<Base, -E>
113119 using NegativePow = Power< typename Pow::base_type, -Pow::exponent >;
114- using merged = typename MergePow < U1, NegativePow >::type;
120+ using merged = typename MergeUnits < U1, NegativePow >::type;
115121public:
116122 using type = typename SubPack< merged, Unit< Tail... > >::type;
117123};
118124
119125// Comparison.hpp -----------------------------------------------------------------------------
120126
121-
122-
123- // Appends `Head` in front of `Unit<Powers...>`
124- template <typename UnitT, typename Head>
125- struct Prepend ;
126-
127- template <typename Head, typename ... Powers>
128- struct Prepend <Unit<Powers...>, Head>
129- {
130- using type = Unit<Head, Powers...>;
131- };
132-
133-
134127// A simple trait that assigns each base type an integer “rank.”
135128template < typename Tag >
136129struct CanonicalOrder ;
137130
138- template < typename P1, typename P2 >
139- struct LessThan
131+ // The comparator uses CanonicalOrder< T >::value to compare.
132+ struct CanonicalUnitComparitor
140133{
141- // P1 and P2 are each PowUnit<SomeBase, Exp>.
142- static constexpr bool value = ( CanonicalOrder< typename P1::base_type >::value < CanonicalOrder< typename P2::base_type >::value );
143- };
144-
145- // A minimal compile-time insertion sort:
146- template < typename SortedList, typename Element >
147- struct InsertSorted ; // forward declaration
148-
149- // Base case: Insert into an empty list
150- template < typename Element >
151- struct InsertSorted < Unit< >, Element >
152- {
153- using type = Unit< Element >;
154- };
155-
156- // Recursive: Compare with the first item of SortedList
157- template < typename First, typename ... Rest, typename Element >
158- struct InsertSorted < Unit< First, Rest... >, Element >
159- {
160- // Compare base orders: if Element < First, put Element in front
161- static constexpr bool insertHere = LessThan< Element, First >::value;
162- using TailSortedInsertion = typename InsertSorted< Unit< Rest... >, Element >::type;
163-
164- using type = std::conditional_t <
165- insertHere,
166- // If we insert here: [Element, First, Rest...]
167- Unit< Element, First, Rest... >,
168- // Keep First, then insert Element into the tail
169- typename Prepend< TailSortedInsertion, First >::type
170- >;
171- };
172-
173- template < typename UnsortedList >
174- struct SortPowers ;
175-
176- // Empty list is already sorted
177- template < >
178- struct SortPowers < Unit< > >
179- {
180- using type = Unit< >;
134+ template < typename P1, typename P2 >
135+ struct compare
136+ {
137+ static constexpr bool value = ( CanonicalOrder< typename P1::base_type >::value < CanonicalOrder< typename P2::base_type >::value );
138+ };
181139};
182140
183- // If there's at least one power: sort the tail, then insert the head
184- template < typename First, typename ... Rest >
185- struct SortPowers < Unit< First, Rest... > >
186- {
187- private:
188- using SortedTail = typename SortPowers< Unit< Rest... > >::type;
189-
190- public:
191- using type = typename InsertSorted< SortedTail, First >::type;
192- };
141+ template < typename UnsortedUnit >
142+ using CanonicalUnit = typename SortPack< Unit, CanonicalUnitComparitor, UnsortedUnit >::type;
193143
194144// / are_same_units< U1, U2> : check if two Unit<...> have the same (Base,Exp) pairs
195145template < typename U1, typename U2 >
@@ -200,10 +150,10 @@ struct are_same_units< Unit< P1s... >, Unit< P2s... > >
200150{
201151private:
202152 // Sort both packs to canonical order
203- using U1Sorted = typename SortPowers< U1 >::type;
204- using U2Sorted = typename SortPowers< U2 >::type;
153+ using CanonicalU1 = typename CanonicalUnit< Unit< P1s... > >::type;
154+ using CanonicalU2 = typename CanonicalUnit< Unit< P2s... > >::type;
205155public:
206- static constexpr bool value = std::is_same< U1Sorted, U2Sorted >::value;
156+ static constexpr bool value = std::is_same< CanonicalU1, CanonicalU2 >::value;
207157};
208158
209159// -----------------------------------------------------------------------------
@@ -222,16 +172,16 @@ struct Divide
222172 using type = typename SubPack< U1, U2 >::type;
223173};
224174
225- // / Invert<U> -> NegatePack
175+ // / Invert<U> -> Negate
226176template < typename U >
227177struct Invert
228178{
229- using type = typename NegatePack < U >::type;
179+ using type = typename Negate < U >::type;
230180};
231181
232182// -----------------------------------------------------------------------------
233183
234- #define ENABLE_UNITGUARD 1 ;
184+ #define ENABLE_UNITGUARD 1
235185#if ENABLE_UNITGUARD == 1
236186template < typename T, typename U >
237187class Quantity
0 commit comments