diff --git a/example/include/ranged_representation.h b/example/include/ranged_representation.h index 0ffd5d70d..1643ec68b 100644 --- a/example/include/ranged_representation.h +++ b/example/include/ranged_representation.h @@ -62,9 +62,6 @@ class ranged_representation : public validated_type -constexpr bool mp_units::is_scalar> = mp_units::is_scalar; - template struct MP_UNITS_STD_FMT::formatter, Char> : formatter { template diff --git a/example/include/validated_type.h b/example/include/validated_type.h index 70be6dac3..67ae53354 100644 --- a/example/include/validated_type.h +++ b/example/include/validated_type.h @@ -113,9 +113,6 @@ class validated_type { = default; }; -template -constexpr bool mp_units::is_scalar> = mp_units::is_scalar; - template std::basic_ostream& operator<<(std::basic_ostream& os, diff --git a/example/kalman_filter/kalman_filter-example_2.cpp b/example/kalman_filter/kalman_filter-example_2.cpp index 5a07edebd..9a3c562c7 100644 --- a/example/kalman_filter/kalman_filter-example_2.cpp +++ b/example/kalman_filter/kalman_filter-example_2.cpp @@ -38,10 +38,6 @@ import mp_units; // Based on: https://www.kalmanfilter.net/alphabeta.html#ex2 -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - using namespace mp_units; void print_header(const kalman::SystemState auto& initial) diff --git a/example/kalman_filter/kalman_filter-example_3.cpp b/example/kalman_filter/kalman_filter-example_3.cpp index 65aa2b1f2..437ffc172 100644 --- a/example/kalman_filter/kalman_filter-example_3.cpp +++ b/example/kalman_filter/kalman_filter-example_3.cpp @@ -38,10 +38,6 @@ import mp_units; // Based on: https://www.kalmanfilter.net/alphabeta.html#ex3 -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - using namespace mp_units; void print_header(const kalman::SystemState auto& initial) diff --git a/example/kalman_filter/kalman_filter-example_4.cpp b/example/kalman_filter/kalman_filter-example_4.cpp index 64e240e1f..d28b591fb 100644 --- a/example/kalman_filter/kalman_filter-example_4.cpp +++ b/example/kalman_filter/kalman_filter-example_4.cpp @@ -38,10 +38,6 @@ import mp_units; // Based on: https://www.kalmanfilter.net/alphabeta.html#ex4 -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - using namespace mp_units; void print_header(const kalman::SystemState auto& initial) diff --git a/example/measurement.cpp b/example/measurement.cpp index 596361132..1f291cee2 100644 --- a/example/measurement.cpp +++ b/example/measurement.cpp @@ -124,6 +124,13 @@ class measurement { return os << v.value() << " ± " << v.uncertainty(); } + [[nodiscard]] friend constexpr measurement abs(const measurement& v) + requires requires { abs(v.value()); } || requires { std::abs(v.value()); } + { + using std::abs; + return measurement(abs(v.value()), v.uncertainty()); + } + private: value_type value_{}; value_type uncertainty_{}; @@ -131,12 +138,8 @@ class measurement { } // namespace -template -constexpr bool mp_units::is_scalar> = true; -template -constexpr bool mp_units::is_vector> = true; - static_assert(mp_units::RepresentationOf, mp_units::quantity_character::scalar>); +static_assert(mp_units::RepresentationOf, mp_units::quantity_character::vector>); namespace { diff --git a/example/storage_tank.cpp b/example/storage_tank.cpp index 86bc32ffa..e733f56f4 100644 --- a/example/storage_tank.cpp +++ b/example/storage_tank.cpp @@ -40,12 +40,6 @@ import mp_units; #include #endif -// allows standard gravity (acceleration) and weight (force) to be expressed with scalar representation -// types instead of requiring the usage of Linear Algebra library for this simple example -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - namespace { using namespace mp_units; diff --git a/example/strong_angular_quantities.cpp b/example/strong_angular_quantities.cpp index 9c03b36c1..88b80abe0 100644 --- a/example/strong_angular_quantities.cpp +++ b/example/strong_angular_quantities.cpp @@ -33,10 +33,6 @@ import mp_units; #include #endif -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - int main() { using namespace mp_units; diff --git a/example/total_energy.cpp b/example/total_energy.cpp index 75416bb7f..eced87bba 100644 --- a/example/total_energy.cpp +++ b/example/total_energy.cpp @@ -37,10 +37,6 @@ import mp_units; #include #endif -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - namespace { using namespace mp_units; diff --git a/src/core/include/mp-units/cartesian_vector.h b/src/core/include/mp-units/cartesian_vector.h index af5e7e366..4af2679ab 100644 --- a/src/core/include/mp-units/cartesian_vector.h +++ b/src/core/include/mp-units/cartesian_vector.h @@ -215,7 +215,7 @@ class cartesian_vector { lhs._coordinates_[2] == rhs._coordinates_[2]; } - [[nodiscard]] friend constexpr T norm(const cartesian_vector& vec) + [[nodiscard]] friend constexpr T magnitude(const cartesian_vector& vec) requires treat_as_floating_point { return vec.magnitude(); @@ -263,9 +263,6 @@ template requires(sizeof...(Args) <= 2) && requires { typename std::common_type_t; } cartesian_vector(Arg, Args...) -> cartesian_vector>; -template -constexpr bool is_vector> = true; - } // namespace mp_units #if MP_UNITS_HOSTED diff --git a/src/core/include/mp-units/complex.h b/src/core/include/mp-units/complex.h index 9f09c05f7..537fbcc87 100644 --- a/src/core/include/mp-units/complex.h +++ b/src/core/include/mp-units/complex.h @@ -25,7 +25,7 @@ #include // #include -#include +#include #ifndef MP_UNITS_IN_MODULE_INTERFACE #ifdef MP_UNITS_IMPORT_STD @@ -38,6 +38,6 @@ import std; namespace mp_units { template -constexpr bool is_complex> = true; +constexpr bool disable_scalar> = true; -} +} // namespace mp_units diff --git a/src/core/include/mp-units/framework/customization_points.h b/src/core/include/mp-units/framework/customization_points.h index 43f8cfff2..f12fb0ef1 100644 --- a/src/core/include/mp-units/framework/customization_points.h +++ b/src/core/include/mp-units/framework/customization_points.h @@ -60,157 +60,22 @@ constexpr bool treat_as_floating_point = std::is_floating_point_v>; #endif -/** - * @brief Specifies a type to have a scalar character - * - * A scalar is a physical quantity that has magnitude but no direction. - */ template -constexpr bool is_scalar = std::is_floating_point_v || (std::is_integral_v && !is_same_v); +[[deprecated("`is_scalar` is no longer necessary and can simply be removed")]] +constexpr bool is_scalar = false; -/** - * @brief Specifies a type to have a complex character - * - * A complex is a physical quantity that has a complex representation type. - */ template +[[deprecated("`is_complex` is no longer necessary and can simply be removed")]] constexpr bool is_complex = false; -/** - * @brief Specifies a type to have a vector character - * - * Vectors are physical quantities that possess both magnitude and direction - * and whose operations obey the axioms of a vector space. - * - * In specific cases a scalar can represent a vector with the default direction. - * If that is the intent, a user should provide a partial specialization: - * - * @code{.cpp} - * template - * requires mp_units::is_scalar - * constexpr bool mp_units::is_vector = true; - * @endcode - */ template +[[deprecated("`is_vector` is no longer necessary and can simply be removed")]] constexpr bool is_vector = false; -/** - * @brief Specifies a type to have a tensor character - * - * Tensors can be used to describe more general physical quantities. - * - * A vector is a tensor of the first order and a scalar is a tensor of order zero. - * Similarly to `is_vector` a partial specialization is needed in such cases. - */ template +[[deprecated("`is_tensor` is no longer necessary and can simply be removed")]] constexpr bool is_tensor = false; -MP_UNITS_EXPORT_END - -namespace detail::norm_impl { - -void norm() = delete; // poison pill - -struct norm_t { - template - [[nodiscard]] constexpr auto operator()(const T& vec) const - { - if constexpr (requires { vec.norm(); }) - return vec.norm(); - else if constexpr (requires { norm(vec); }) - return norm(vec); - else if constexpr (requires { vec.magnitude(); }) - return vec.magnitude(); - else if constexpr (requires { magnitude(vec); }) - return magnitude(vec); - // TODO Is it a good idea to enable fundamental types to represent vector quantities? - // else if constexpr (is_scalar) - // return std::abs(vec); - } -}; - -} // namespace detail::norm_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::norm_impl::norm_t norm; - -} - -namespace detail::real_impl { - -void real() = delete; // poison pill - -struct real_t { - template - [[nodiscard]] constexpr auto operator()(const T& clx) const - { - if constexpr (requires { clx.real(); }) - return clx.real(); - else if constexpr (requires { real(clx); }) - return real(clx); - } -}; - -} // namespace detail::real_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::real_impl::real_t real; - -} - -namespace detail::imag_impl { - -void imag() = delete; // poison pill - -struct imag_t { - template - [[nodiscard]] constexpr auto operator()(const T& clx) const - { - if constexpr (requires { clx.imag(); }) - return clx.imag(); - else if constexpr (requires { imag(clx); }) - return imag(clx); - } -}; - -} // namespace detail::imag_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::imag_impl::imag_t imag; - -} - -namespace detail::modulus_impl { - -void modulus() = delete; // poison pill - -struct modulus_t { - template - [[nodiscard]] constexpr auto operator()(const T& clx) const - { - if constexpr (requires { clx.modulus(); }) - return clx.modulus(); - else if constexpr (requires { modulus(clx); }) - return modulus(clx); - // `std` made a precedence of using `abs` for modulo on `std::complex` - else if constexpr (requires { abs(clx); }) - return abs(clx); - } -}; - -} // namespace detail::modulus_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::modulus_impl::modulus_t modulus; - -} - -MP_UNITS_EXPORT_BEGIN - /** * @brief A type trait that defines zero, one, min, and max for a representation type * diff --git a/src/core/include/mp-units/framework/quantity_concepts.h b/src/core/include/mp-units/framework/quantity_concepts.h index 275763ce7..c4bba5e32 100644 --- a/src/core/include/mp-units/framework/quantity_concepts.h +++ b/src/core/include/mp-units/framework/quantity_concepts.h @@ -43,6 +43,10 @@ template constexpr bool is_derived_from_specialization_of_quantity = requires(T* type) { to_base_specialization_of_quantity(type); }; +template + requires is_derived_from_specialization_of_quantity +constexpr bool is_quantity = true; + } // namespace detail /** diff --git a/src/core/include/mp-units/framework/representation_concepts.h b/src/core/include/mp-units/framework/representation_concepts.h index 66a6db2ff..414c08752 100644 --- a/src/core/include/mp-units/framework/representation_concepts.h +++ b/src/core/include/mp-units/framework/representation_concepts.h @@ -33,10 +33,11 @@ import std; #else #include #include +#include #include #include -#endif -#endif +#endif // MP_UNITS_IMPORT_STD +#endif // MP_UNITS_IN_MODULE_INTERFACE namespace mp_units { @@ -62,105 +63,244 @@ namespace mp_units { */ MP_UNITS_EXPORT enum class quantity_character : std::int8_t { scalar, complex, vector, tensor }; +MP_UNITS_EXPORT template +constexpr bool disable_scalar = false; + +template<> +MP_UNITS_INLINE constexpr bool disable_scalar = true; + namespace detail { template concept WeaklyRegular = std::copyable && std::equality_comparable; template -concept Scalar = is_scalar; +concept Scalar = (!disable_scalar) && WeaklyRegular && requires(T a, T b) { + // scalar operations + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + { a* b } -> std::common_with; + { a / b } -> std::common_with; +}; -template -concept Complex = is_complex; +namespace real_impl { + +void real() = delete; // poison pill + +struct real_t { + [[nodiscard]] constexpr Scalar auto operator()(const WeaklyRegular auto& clx) const + requires requires { clx.real(); } || requires { real(clx); } + { + if constexpr (requires { clx.real(); }) + return clx.real(); + else if constexpr (requires { real(clx); }) + return real(clx); + } +}; + +} // namespace real_impl + +} // namespace detail + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::real_impl::real_t real; + +} + +namespace detail::imag_impl { + +void imag() = delete; // poison pill + +struct imag_t { + [[nodiscard]] constexpr Scalar auto operator()(const WeaklyRegular auto& clx) const + requires requires { clx.imag(); } || requires { imag(clx); } + { + if constexpr (requires { clx.imag(); }) + return clx.imag(); + else if constexpr (requires { imag(clx); }) + return imag(clx); + } +}; + +} // namespace detail::imag_impl + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::imag_impl::imag_t imag; + +} + +namespace detail::modulus_impl { + +void modulus() = delete; // poison pill +void abs() = delete; // poison pill + +struct modulus_t { + [[nodiscard]] constexpr Scalar auto operator()(const WeaklyRegular auto& clx) const + requires requires { clx.modulus(); } || requires { modulus(clx); } || requires { clx.abs(); } || + requires { abs(clx); } + { + if constexpr (requires { clx.modulus(); }) + return clx.modulus(); + else if constexpr (requires { modulus(clx); }) + return modulus(clx); + // `std` made a precedence of using `abs` for modulo on `std::complex` + else if constexpr (requires { clx.abs(); }) + return clx.abs(); + else if constexpr (requires { abs(clx); }) + return abs(clx); + } +}; + +} // namespace detail::modulus_impl + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::modulus_impl::modulus_t modulus; + +} + +MP_UNITS_EXPORT template +constexpr bool disable_complex = false; + +namespace detail { template -concept Vector = is_vector; +concept Complex = + (!disable_complex) && WeaklyRegular && Scalar> && + std::constructible_from, value_type_t> && requires(T a, T b, value_type_t s) { + // complex operations + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + { a* b } -> std::common_with; + { a / b } -> std::common_with; + { a* s } -> std::common_with; + { s* a } -> std::common_with; + { a / s } -> std::common_with; + ::mp_units::real(a); + ::mp_units::imag(a); + ::mp_units::modulus(a); + }; + +namespace magnitude_impl { + +void magnitude() = delete; // poison pill +void abs() = delete; // poison pill + +struct magnitude_t { + template + [[nodiscard]] constexpr Scalar auto operator()(const T& vec) const + requires requires { vec.magnitude(); } || requires { magnitude(vec); } || + (Scalar && + (requires { vec.abs(); } || requires { abs(vec); } || (std::is_arithmetic_v && (!is_same_v)))) + { + if constexpr (requires { vec.magnitude(); }) + return vec.magnitude(); + else if constexpr (requires { magnitude(vec); }) + return magnitude(vec); + // allow scalar types to represent one dimensional vector quantities + if constexpr (Scalar) { + if constexpr (requires { vec.abs(); }) + return vec.abs(); + else if constexpr (requires { abs(vec); }) + return abs(vec); + else if constexpr (std::is_arithmetic_v && (!is_same_v)) +#if MP_UNITS_HOSTED || __cpp_lib_freestanding_cstdlib >= 202306L + return std::abs(vec); +#else + return vec >= 0 ? vec : -vec; +#endif + } + } +}; + +} // namespace magnitude_impl + +} // namespace detail + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::magnitude_impl::magnitude_t magnitude; + +} + +MP_UNITS_EXPORT template +constexpr bool disable_vector = false; + +namespace detail { template -concept Tensor = is_tensor; +concept Vector = + (!disable_vector) && WeaklyRegular && Scalar> && requires(T a, T b, value_type_t s) { + // vector operations + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + { a* s } -> std::common_with; + { s* a } -> std::common_with; + { a / s } -> std::common_with; + ::mp_units::magnitude(a); + // TODO should we check for the below as well (e.g., when `size() > 1` or `2`) + // { zero_vector() } -> Vector; + // { unit_vector(a) } -> Vector; + // { scalar_product(a, b) } -> Scalar; + // { vector_product(a, b) } -> Vector; + // { tensor_product(a, b) } -> Tensor2; + }; -template -concept IsOfCharacter = - (Ch == quantity_character::scalar && is_scalar) || (Ch == quantity_character::complex && is_complex) || - (Ch == quantity_character::vector && is_vector) || (Ch == quantity_character::tensor && is_tensor); +// TODO provide when some actual operations will be required +// template +// concept Tensor = is_tensor && WeaklyRegular; // && requires(T a, T b) { +// // tensor operations +// // { tensor_product(a, b) } -> Tensor4; +// // { inner_product(a, b) } -> Tensor2; +// // { scalar_product(a, b) } -> Scalar; +// //}; + +template +constexpr bool is_quantity = false; template using scaling_factor_type_t = conditional, long double, std::intmax_t>; template -concept ScalarRepresentation = Scalar && WeaklyRegular && requires(T a, T b, scaling_factor_type_t f) { +concept ScalarRepresentation = (!is_quantity) && Scalar && requires(T a, T b, scaling_factor_type_t f) { // scaling - { a* f } -> Scalar; - { f* a } -> Scalar; - { a / f } -> Scalar; - - // scalar operations - { -a } -> Scalar; - { a + b } -> Scalar; - { a - b } -> Scalar; - { a* b } -> Scalar; - { a / b } -> Scalar; + { a* f } -> std::common_with; + { f* a } -> std::common_with; + { a / f } -> std::common_with; }; template -concept ComplexRepresentation = Complex && WeaklyRegular && requires(T a, T b, scaling_factor_type_t f) { +concept ComplexRepresentation = (!is_quantity) && Complex && requires(T a, T b, scaling_factor_type_t f) { // scaling // TODO The below conversion to `T` is an exception compared to other representation types // `std::complex` * `U` do not work, but `std::complex` is convertible from `U` // Maybe expose this as a customization point? - { a* T(f) } -> Complex; - { T(f) * a } -> Complex; - { a / T(f) } -> Complex; - - // complex operations - { -a } -> Complex; - { a + b } -> Complex; - { a - b } -> Complex; - { a* b } -> Complex; - { a / b } -> Complex; - { ::mp_units::real(a) } -> Scalar; - { ::mp_units::imag(a) } -> Scalar; - { ::mp_units::modulus(a) } -> Scalar; + { a* T(f) } -> std::common_with; + { T(f) * a } -> std::common_with; + { a / T(f) } -> std::common_with; }; -// TODO how to check for a complex(Scalar, Scalar) -> Complex? - template -concept VectorRepresentation = Vector && WeaklyRegular && requires(T a, T b, scaling_factor_type_t f) { - // scaling - { a* f } -> Vector; - { f* a } -> Vector; - { a / f } -> Vector; - - // vector operations - { -a } -> Vector; - { a + b } -> Vector; - { a - b } -> Vector; - { ::mp_units::norm(a) } -> Scalar; - // TBD - // { zero_vector() } -> Vector; - // { unit_vector(a) } -> Vector; - // { scalar_product(a, b) } -> Scalar; - // { vector_product(a, b) } -> Vector; - // { tensor_product(a, b) } -> Tensor2; - // divergence(a) - // rotation(a) -}; +concept VectorRepresentation = (!is_quantity) && Vector; -template -concept TensorRepresentation = Tensor && WeaklyRegular; // && requires(T a, T b) { - // TBD - // tensor operations - // { tensor_product(a, b) } -> Tensor4; - // { inner_product(a, b) } -> Tensor2; - // { scalar_product(a, b) } -> Scalar; -//}; +// template +// concept TensorRepresentation = (!is_quantity) && Tensor; + +template +concept IsOfCharacter = + (Ch == quantity_character::scalar && Scalar) || (Ch == quantity_character::complex && Complex) || + (Ch == quantity_character::vector && Vector); // || (Ch == quantity_character::tensor && Tensor); } // namespace detail MP_UNITS_EXPORT template concept Representation = detail::ScalarRepresentation || detail::ComplexRepresentation || - detail::VectorRepresentation || detail::TensorRepresentation; + detail::VectorRepresentation; // || detail::TensorRepresentation; MP_UNITS_EXPORT template concept RepresentationOf = diff --git a/test/runtime/linear_algebra_test.cpp b/test/runtime/linear_algebra_test.cpp index 85a7afc72..200bf644b 100644 --- a/test/runtime/linear_algebra_test.cpp +++ b/test/runtime/linear_algebra_test.cpp @@ -43,12 +43,6 @@ import mp_units; template using vector = STD_LA::fixed_size_column_vector; -template -constexpr bool mp_units::treat_as_floating_point> = mp_units::treat_as_floating_point; - -template -constexpr bool mp_units::is_vector> = true; - template std::ostream& operator<<(std::ostream& os, const vector& v) { @@ -87,8 +81,6 @@ template } template - requires is_vector && is_vector && - requires(typename Q1::rep v1, typename Q2::rep v2) { cross_product(v1, v2); } [[nodiscard]] constexpr QuantityOf auto cross_product(const Q1& q1, const Q2& q2) { return cross_product(q1.numerical_value_ref_in(q1.unit), q2.numerical_value_ref_in(q2.unit)) * @@ -299,10 +291,6 @@ TEST_CASE("vector quantity", "[la]") } } -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - TEST_CASE("vector of quantities", "[la]") { SECTION("cast of unit") diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index fbd20241a..d0d4552b0 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -278,13 +278,16 @@ static_assert(!Representation); // RepresentationOf static_assert(RepresentationOf); static_assert(!RepresentationOf); -static_assert(!RepresentationOf); +static_assert(RepresentationOf); static_assert(!RepresentationOf); static_assert(RepresentationOf); static_assert(!RepresentationOf); -static_assert(!RepresentationOf); +static_assert(RepresentationOf); static_assert(!RepresentationOf); static_assert(!RepresentationOf); +static_assert(!RepresentationOf); +static_assert(!RepresentationOf); +static_assert(!RepresentationOf); static_assert(!RepresentationOf, quantity_character::scalar>); #if MP_UNITS_HOSTED static_assert(RepresentationOf, quantity_character::complex>); diff --git a/test/static/custom_rep_test_min_impl.cpp b/test/static/custom_rep_test_min_impl.cpp index e2810eaac..a07524d04 100644 --- a/test/static/custom_rep_test_min_impl.cpp +++ b/test/static/custom_rep_test_min_impl.cpp @@ -60,9 +60,6 @@ class min_impl { } // namespace -template -constexpr bool mp_units::is_scalar> = true; - template struct std::common_type, min_impl> : std::type_identity>> {}; template diff --git a/test/static/hep_test.cpp b/test/static/hep_test.cpp index 62407bd40..623963f55 100644 --- a/test/static/hep_test.cpp +++ b/test/static/hep_test.cpp @@ -24,10 +24,6 @@ #include #include -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - namespace { using namespace mp_units; diff --git a/test/static/international_test.cpp b/test/static/international_test.cpp index 755eea73c..8d845f9a9 100644 --- a/test/static/international_test.cpp +++ b/test/static/international_test.cpp @@ -26,10 +26,6 @@ #include #include -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - namespace { using namespace mp_units; diff --git a/test/static/natural_test.cpp b/test/static/natural_test.cpp index 9986149a5..3281192fd 100644 --- a/test/static/natural_test.cpp +++ b/test/static/natural_test.cpp @@ -22,10 +22,6 @@ #include -template - requires mp_units::is_scalar -constexpr bool mp_units::is_vector = true; - namespace { using namespace mp_units; diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index a9a4a5e74..3b8d14d58 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -47,9 +47,6 @@ import std; #endif #endif -template<> -constexpr bool mp_units::is_vector = true; - namespace { using namespace mp_units; @@ -74,8 +71,10 @@ concept invalid_types = requires { requires !requires { typename Q; }; // quantity_spec instead of reference requires !requires { typename Q; }; // bool is not a valid representation type requires !requires { typename Q>; }; // quantity used as Rep - requires !requires { typename Q; }; // vector representation expected #if MP_UNITS_HOSTED + requires !requires { + typename Q>; + }; // vector representation expected requires !requires { typename Q>; }; // scalar representation expected