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,91 @@ 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::is_quantity<S>) &&
187+ requires (const T& t, const S& s) { t * s; }
188+ [[nodiscard]] friend constexpr auto operator *(const cartesian_vector& vector, const S& scalar)
189+ {
190+ return ::mp_units::cartesian_vector{vector._coordinates_ [0 ] * scalar, vector._coordinates_ [1 ] * scalar,
191+ vector._coordinates_ [2 ] * scalar};
192+ }
193+
194+ template <typename S>
195+ requires (!std::same_as<std::remove_cvref_t <S>, cartesian_vector>) && (!detail::is_quantity<S>) &&
196+ requires (const S& s, const T& t) { s * t; }
197+ [[nodiscard]] friend constexpr auto operator *(const S& scalar, const cartesian_vector& vector)
198+ {
199+ return vector * scalar;
200+ }
201+
202+ template <typename S>
203+ requires (!std::same_as<std::remove_cvref_t <S>, cartesian_vector>) && (!detail::is_quantity<S>) &&
204+ requires (const T& t, const S& s) { t / s; }
205+ [[nodiscard]] friend constexpr auto operator /(const cartesian_vector& vector, const S& scalar)
206+ {
207+ return ::mp_units::cartesian_vector{vector._coordinates_ [0 ] / scalar, vector._coordinates_ [1 ] / scalar,
208+ vector._coordinates_ [2 ] / scalar};
209+ }
210+
211+ template <std::equality_comparable_with<T> U>
212+ [[nodiscard]] friend constexpr bool operator ==(const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
213+ {
214+ return lhs._coordinates_ [0 ] == rhs._coordinates_ [0 ] && lhs._coordinates_ [1 ] == rhs._coordinates_ [1 ] &&
215+ lhs._coordinates_ [2 ] == rhs._coordinates_ [2 ];
216+ }
217+
218+ template <typename U>
219+ requires requires (const T& t, const U& u, decltype (t * u) v) {
220+ t * u;
221+ v + v;
222+ }
223+ [[nodiscard]] friend constexpr auto scalar_product (const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
224+ {
225+ return lhs._coordinates_ [0 ] * rhs._coordinates_ [0 ] + lhs._coordinates_ [1 ] * rhs._coordinates_ [1 ] +
226+ lhs._coordinates_ [2 ] * rhs._coordinates_ [2 ];
227+ }
228+
229+ template <typename U>
230+ requires requires (const T& t, const U& u, decltype (t * u) v) {
231+ t * u;
232+ v - v;
233+ }
234+ [[nodiscard]] friend constexpr auto vector_product (const cartesian_vector& lhs, const cartesian_vector<U>& rhs)
235+ {
236+ return ::mp_units::cartesian_vector{
237+ lhs._coordinates_ [1 ] * rhs._coordinates_ [2 ] - lhs._coordinates_ [2 ] * rhs._coordinates_ [1 ],
238+ lhs._coordinates_ [2 ] * rhs._coordinates_ [0 ] - lhs._coordinates_ [0 ] * rhs._coordinates_ [2 ],
239+ lhs._coordinates_ [0 ] * rhs._coordinates_ [1 ] - lhs._coordinates_ [1 ] * rhs._coordinates_ [0 ]};
240+ }
241+
145242#if MP_UNITS_HOSTED
146243 friend std::ostream& operator <<(std::ostream& os, const cartesian_vector& vec)
147244 {
@@ -154,88 +251,6 @@ template<typename Arg, typename... Args>
154251 requires (sizeof ...(Args) <= 2 ) && requires { typename std::common_type_t <Arg, Args...>; }
155252cartesian_vector (Arg, Args...) -> cartesian_vector<std::common_type_t <Arg, Args...>>;
156253
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-
239254template <class T >
240255inline constexpr bool treat_as_floating_point<cartesian_vector<T>> = treat_as_floating_point<T>;
241256
0 commit comments