2222
2323#pragma once
2424
25- #include < mp-units/bits/module_macros.h>
2625#include < mp-units/bits/requires_hosted.h>
26+ #include < mp-units/bits/module_macros.h>
2727#include < mp-units/framework/customization_points.h>
2828#include < mp-units/framework/representation_concepts.h>
2929#include < type_traits>
@@ -56,10 +56,22 @@ MP_UNITS_EXPORT template<detail::Scalar T = double>
5656class cartesian_vector {
5757public:
5858 // public members required to satisfy structural type requirements :-(
59- // NOTE: This type is intentionally an aggregate (like std::array).
6059 T _coordinates_[3 ];
6160 using value_type = T;
6261
62+ constexpr cartesian_vector () = default;
63+
64+ explicit constexpr cartesian_vector (T x) : _coordinates_{x, T{}, T{}} {}
65+ constexpr cartesian_vector (T x, T y) : _coordinates_{x, y, T{}} {}
66+ constexpr cartesian_vector (T x, T y, T z) : _coordinates_{x, y, z} {}
67+
68+ template <typename U>
69+ requires std::constructible_from<T, U> && (!std::same_as<std::remove_cvref_t <U>, T>) &&
70+ (!std::same_as<std::remove_cvref_t <U>, cartesian_vector>)
71+ explicit constexpr cartesian_vector (U&& val) : _coordinates_{T (val), T (val), T (val)}
72+ {
73+ }
74+
6375 [[nodiscard]] constexpr T magnitude () const
6476 requires treat_as_floating_point<T>
6577 {
@@ -142,6 +154,88 @@ class cartesian_vector {
142154 return vec.unit ();
143155 }
144156
157+ template <typename U>
158+ requires requires (const T& t, const U& u) { t + u; }
159+ [[nodiscard]] friend constexpr auto operator +(const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
160+ {
161+ return ::mp_units::cartesian_vector{lhs._coordinates_ [0 ] + rhs._coordinates_ [0 ],
162+ lhs._coordinates_ [1 ] + rhs._coordinates_ [1 ],
163+ lhs._coordinates_ [2 ] + rhs._coordinates_ [2 ]};
164+ }
165+
166+ template <typename U>
167+ requires requires (const T& t, const U& u) { t - u; }
168+ [[nodiscard]] friend constexpr auto operator -(const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
169+ {
170+ return ::mp_units::cartesian_vector{lhs._coordinates_ [0 ] - rhs._coordinates_ [0 ],
171+ lhs._coordinates_ [1 ] - rhs._coordinates_ [1 ],
172+ lhs._coordinates_ [2 ] - rhs._coordinates_ [2 ]};
173+ }
174+
175+ template <typename U>
176+ requires (!treat_as_floating_point<T> && !treat_as_floating_point<U> && requires (const T& t, const U& u) { t % u; })
177+ [[nodiscard]] friend constexpr auto operator %(const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
178+ {
179+ using CT = std::common_type_t <T, U>;
180+ return ::mp_units::cartesian_vector<CT>{static_cast <CT>(lhs._coordinates_ [0 ] % rhs._coordinates_ [0 ]),
181+ static_cast <CT>(lhs._coordinates_ [1 ] % rhs._coordinates_ [1 ]),
182+ static_cast <CT>(lhs._coordinates_ [2 ] % rhs._coordinates_ [2 ])};
183+ }
184+
185+ template <typename S>
186+ requires (!std::same_as<std::remove_cvref_t <S>, cartesian_vector>) && detail::NotQuantity<S>
187+ [[nodiscard]] friend constexpr auto operator *(const cartesian_vector& vector, const S& scalar)
188+ {
189+ return ::mp_units::cartesian_vector{vector._coordinates_ [0 ] * scalar, vector._coordinates_ [1 ] * scalar,
190+ vector._coordinates_ [2 ] * scalar};
191+ }
192+
193+ template <typename S>
194+ requires (!std::same_as<std::remove_cvref_t <S>, cartesian_vector>) && detail::NotQuantity<S>
195+ [[nodiscard]] friend constexpr auto operator *(const S& scalar, const cartesian_vector& vector)
196+ {
197+ return vector * scalar;
198+ }
199+
200+ template <typename S>
201+ requires (!std::same_as<std::remove_cvref_t <S>, cartesian_vector>) && detail::NotQuantity<S>
202+ [[nodiscard]] friend constexpr auto operator /(const cartesian_vector& vector, const S& scalar)
203+ {
204+ return ::mp_units::cartesian_vector{vector._coordinates_ [0 ] / scalar, vector._coordinates_ [1 ] / scalar,
205+ vector._coordinates_ [2 ] / scalar};
206+ }
207+
208+ template <std::equality_comparable_with<T> U>
209+ [[nodiscard]] friend constexpr bool operator ==(const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
210+ {
211+ return lhs._coordinates_ [0 ] == rhs._coordinates_ [0 ] && lhs._coordinates_ [1 ] == rhs._coordinates_ [1 ] &&
212+ lhs._coordinates_ [2 ] == rhs._coordinates_ [2 ];
213+ }
214+
215+ template <typename U>
216+ requires requires (const T& t, const U& u, decltype (t * u) v) {
217+ t * u;
218+ v + v;
219+ }
220+ [[nodiscard]] friend constexpr auto scalar_product (const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
221+ {
222+ return lhs._coordinates_ [0 ] * rhs._coordinates_ [0 ] + lhs._coordinates_ [1 ] * rhs._coordinates_ [1 ] +
223+ lhs._coordinates_ [2 ] * rhs._coordinates_ [2 ];
224+ }
225+
226+ template <typename U>
227+ requires requires (const T& t, const U& u, decltype (t * u) v) {
228+ t * u;
229+ v - v;
230+ }
231+ [[nodiscard]] friend constexpr auto vector_product (const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
232+ {
233+ return ::mp_units::cartesian_vector{
234+ lhs._coordinates_ [1 ] * rhs._coordinates_ [2 ] - lhs._coordinates_ [2 ] * rhs._coordinates_ [1 ],
235+ lhs._coordinates_ [2 ] * rhs._coordinates_ [0 ] - lhs._coordinates_ [0 ] * rhs._coordinates_ [2 ],
236+ lhs._coordinates_ [0 ] * rhs._coordinates_ [1 ] - lhs._coordinates_ [1 ] * rhs._coordinates_ [0 ]};
237+ }
238+
145239#if MP_UNITS_HOSTED
146240 friend std::ostream& operator <<(std::ostream& os, const cartesian_vector& vec)
147241 {
@@ -154,88 +248,6 @@ template<typename Arg, typename... Args>
154248 requires (sizeof ...(Args) <= 2 ) && requires { typename std::common_type_t <Arg, Args...>; }
155249cartesian_vector (Arg, Args...) -> cartesian_vector<std::common_type_t <Arg, Args...>>;
156250
157- MP_UNITS_EXPORT template <typename T, typename U>
158- requires requires (const T& t, const U& u) { t + u; }
159- [[nodiscard]] constexpr auto operator +(const cartesian_vector<T>& lhs, const cartesian_vector<U>& rhs)
160- {
161- return ::mp_units::cartesian_vector{lhs._coordinates_ [0 ] + rhs._coordinates_ [0 ],
162- lhs._coordinates_ [1 ] + rhs._coordinates_ [1 ],
163- lhs._coordinates_ [2 ] + rhs._coordinates_ [2 ]};
164- }
165-
166- MP_UNITS_EXPORT template <typename T, typename U>
167- requires requires (const T& t, const U& u) { t - u; }
168- [[nodiscard]] constexpr auto operator -(const cartesian_vector<T>& lhs, const cartesian_vector<U>& rhs)
169- {
170- return ::mp_units::cartesian_vector{lhs._coordinates_ [0 ] - rhs._coordinates_ [0 ],
171- lhs._coordinates_ [1 ] - rhs._coordinates_ [1 ],
172- lhs._coordinates_ [2 ] - rhs._coordinates_ [2 ]};
173- }
174-
175- MP_UNITS_EXPORT template <typename T, typename U>
176- requires (!treat_as_floating_point<T> && !treat_as_floating_point<U> && requires (const T& t, const U& u) { t % u; })
177- [[nodiscard]] constexpr auto operator %(const cartesian_vector<T>& lhs, const cartesian_vector<U>& rhs)
178- {
179- using CT = std::common_type_t <T, U>;
180- return ::mp_units::cartesian_vector<CT>{static_cast <CT>(lhs._coordinates_ [0 ] % rhs._coordinates_ [0 ]),
181- static_cast <CT>(lhs._coordinates_ [1 ] % rhs._coordinates_ [1 ]),
182- static_cast <CT>(lhs._coordinates_ [2 ] % rhs._coordinates_ [2 ])};
183- }
184-
185- MP_UNITS_EXPORT template <typename T, typename S>
186- requires requires (const T& t, const S& s) { t * s; }
187- [[nodiscard]] constexpr auto operator *(const cartesian_vector<T>& vector, const S& scalar)
188- {
189- return ::mp_units::cartesian_vector{vector._coordinates_ [0 ] * scalar, vector._coordinates_ [1 ] * scalar,
190- vector._coordinates_ [2 ] * scalar};
191- }
192-
193- MP_UNITS_EXPORT template <typename S, typename U>
194- requires requires (const S& s, const U& u) { s * u; }
195- [[nodiscard]] constexpr auto operator *(const S& scalar, const cartesian_vector<U>& vector)
196- {
197- return vector * scalar;
198- }
199-
200- MP_UNITS_EXPORT template <typename T, typename S>
201- requires requires (const T& t, const S& s) { t / s; }
202- [[nodiscard]] constexpr auto operator /(const cartesian_vector<T>& vector, const S& scalar)
203- {
204- return ::mp_units::cartesian_vector{vector._coordinates_ [0 ] / scalar, vector._coordinates_ [1 ] / scalar,
205- vector._coordinates_ [2 ] / scalar};
206- }
207-
208- MP_UNITS_EXPORT template <typename T, std::equality_comparable_with<T> U>
209- [[nodiscard]] constexpr bool operator ==(const cartesian_vector<T>& lhs, const cartesian_vector<U>& rhs)
210- {
211- return lhs._coordinates_ [0 ] == rhs._coordinates_ [0 ] && lhs._coordinates_ [1 ] == rhs._coordinates_ [1 ] &&
212- lhs._coordinates_ [2 ] == rhs._coordinates_ [2 ];
213- }
214-
215- MP_UNITS_EXPORT template <typename T, typename U>
216- requires requires (const T& t, const U& u, decltype (t * u) v) {
217- t * u;
218- v + v;
219- }
220- [[nodiscard]] constexpr auto scalar_product (const cartesian_vector<T>& lhs, const cartesian_vector<U>& rhs)
221- {
222- return lhs._coordinates_ [0 ] * rhs._coordinates_ [0 ] + lhs._coordinates_ [1 ] * rhs._coordinates_ [1 ] +
223- lhs._coordinates_ [2 ] * rhs._coordinates_ [2 ];
224- }
225-
226- MP_UNITS_EXPORT template <typename T, typename U>
227- requires requires (const T& t, const U& u, decltype (t * u) v) {
228- t * u;
229- v - v;
230- }
231- [[nodiscard]] constexpr auto vector_product (const cartesian_vector<T>& lhs, const cartesian_vector<U>& rhs)
232- {
233- return ::mp_units::cartesian_vector{
234- lhs._coordinates_ [1 ] * rhs._coordinates_ [2 ] - lhs._coordinates_ [2 ] * rhs._coordinates_ [1 ],
235- lhs._coordinates_ [2 ] * rhs._coordinates_ [0 ] - lhs._coordinates_ [0 ] * rhs._coordinates_ [2 ],
236- lhs._coordinates_ [0 ] * rhs._coordinates_ [1 ] - lhs._coordinates_ [1 ] * rhs._coordinates_ [0 ]};
237- }
238-
239251template <class T >
240252inline constexpr bool treat_as_floating_point<cartesian_vector<T>> = treat_as_floating_point<T>;
241253
@@ -271,4 +283,4 @@ struct MP_UNITS_STD_FMT::formatter<mp_units::cartesian_vector<T>, Char> :
271283 return format_to (ctx.out (), " [{}, {}, {}]" , vec[0 ], vec[1 ], vec[2 ]);
272284 }
273285};
274- #endif
286+ #endif
0 commit comments