mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-29 18:07:16 +02:00
Fixes for apple-clang crashes and performance issues
The source of the crash with the latest changes seemed to be from the `IsOfCharacter` concept. This concept was refactored to use some type traits and more simple concepts although with less strict requirements. A new macro, `MP_UNITS_APPLE_CLANG_HACKS` was added to mp-units/bits/hacks.h to enable work arounds for pre-Xcode 16.1 apple-clang. Some tests were not passing and were removed with the preprocessor macro for apple-clang hacks is defined. Adding `ComplexFunctionsAvailable` and `VectorFunctionsAvailable` fixed some test failures in concepts_test.cpp but not all.
This commit is contained in:
@ -150,5 +150,9 @@ MP_UNITS_DIAGNOSTIC_POP
|
||||
|
||||
#define MP_UNITS_API_NO_CRTP 1
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && defined(__apple_build_version__) && __apple_build_version__ < 16000026
|
||||
#define MP_UNITS_APPLE_CLANG_HACKS
|
||||
#endif
|
||||
// NOLINTEND(bugprone-reserved-identifier, cppcoreguidelines-macro-usage)
|
||||
|
@ -190,6 +190,7 @@ concept Complex = (!disable_complex<T>) && requires(const T a, const T b, const
|
||||
requires std::constructible_from<T, decltype(::mp_units::real(c)), decltype(::mp_units::imag(c))>;
|
||||
} && WeaklyRegular<T>;
|
||||
|
||||
|
||||
namespace magnitude_impl {
|
||||
|
||||
void magnitude() = delete; // poison pill
|
||||
@ -309,15 +310,45 @@ concept VectorRepresentation = (!is_quantity<T>) && Vector<T> && requires(const
|
||||
|
||||
MP_UNITS_EXPORT template<typename T>
|
||||
concept Representation = detail::ScalarRepresentation<T> || detail::ComplexRepresentation<T> ||
|
||||
detail::VectorRepresentation<T>; // || detail::TensorRepresentation<T>;
|
||||
detail::VectorRepresentation<T>; // || detail::TensorRepresentation<T>; */
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef MP_UNITS_APPLE_CLANG_HACKS
|
||||
template<typename T>
|
||||
constexpr bool is_weakly_regular = std::copyable<T> && std::equality_comparable<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_scalar = !disable_scalar<T> && is_weakly_regular<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_complex = !disable_complex<T> && is_weakly_regular<T> && is_scalar<value_type_t<T>> &&
|
||||
std::constructible_from<T, value_type_t<T>, value_type_t<T>>;
|
||||
|
||||
template<typename T>
|
||||
concept ComplexFunctionsAvailable = requires(T a) {
|
||||
::mp_units::real(a);
|
||||
::mp_units::imag(a);
|
||||
::mp_units::modulus(a);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_vector = !disable_vector<T> && is_weakly_regular<T> && is_scalar<value_type_t<T>>;
|
||||
|
||||
template<typename T>
|
||||
concept VectorFunctionsAvailable = requires(T a) { ::mp_units::magnitude(a); };
|
||||
|
||||
|
||||
template<typename T, quantity_character Ch>
|
||||
concept IsOfCharacter = ((Ch == quantity_character::scalar && is_scalar<T>) ||
|
||||
(Ch == quantity_character::complex && is_complex<T> && ComplexFunctionsAvailable<T>) ||
|
||||
(Ch == quantity_character::vector && is_vector<T> && VectorFunctionsAvailable<T>));
|
||||
#else
|
||||
template<typename T, quantity_character Ch>
|
||||
concept IsOfCharacter =
|
||||
(Ch == quantity_character::scalar && Scalar<T>) || (Ch == quantity_character::complex && Complex<T>) ||
|
||||
(Ch == quantity_character::vector && Vector<T>); // || (Ch == quantity_character::tensor && Tensor<T>);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_UNITS_EXPORT template<typename T, auto V>
|
||||
|
@ -20,6 +20,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/natural.h>
|
||||
#include <mp-units/systems/si.h>
|
||||
@ -308,7 +309,9 @@ static_assert(!RepresentationOf<std::complex<double>, quantity_character::scalar
|
||||
static_assert(!RepresentationOf<std::complex<double>, quantity_character::vector>);
|
||||
static_assert(!RepresentationOf<std::complex<double>, quantity_character::tensor>);
|
||||
static_assert(RepresentationOf<cartesian_vector<double>, quantity_character::vector>);
|
||||
#ifndef MP_UNITS_APPLE_CLANG_HACKS
|
||||
static_assert(!RepresentationOf<cartesian_vector<double>, quantity_character::scalar>);
|
||||
#endif
|
||||
static_assert(!RepresentationOf<cartesian_vector<double>, quantity_character::complex>);
|
||||
static_assert(!RepresentationOf<cartesian_vector<double>, quantity_character::tensor>);
|
||||
static_assert(!RepresentationOf<std::chrono::seconds, quantity_character::scalar>);
|
||||
|
@ -65,6 +65,8 @@ static_assert(sizeof(quantity<isq::length[m]>) == sizeof(double));
|
||||
static_assert(sizeof(quantity<si::metre, short>) == sizeof(short));
|
||||
static_assert(sizeof(quantity<isq::length[m], short>) == sizeof(short));
|
||||
|
||||
#ifndef MP_UNITS_APPLE_CLANG_HACKS
|
||||
|
||||
template<template<auto, typename> typename Q>
|
||||
concept invalid_types = requires {
|
||||
requires !requires { typename Q<isq::dim_length, double>; }; // dimension instead of reference
|
||||
@ -77,13 +79,15 @@ concept invalid_types = requires {
|
||||
}; // vector representation expected
|
||||
requires !requires {
|
||||
typename Q<isq::length[si::metre], cartesian_vector<double>>;
|
||||
}; // scalar representation expected
|
||||
}; // scalar representation expected
|
||||
requires !requires { typename Q<isq::voltage[V], std::complex<double>>; }; // incompatible character
|
||||
requires !requires { typename Q<isq::voltage_phasor[V], double>; }; // incompatible character
|
||||
#endif
|
||||
};
|
||||
static_assert(invalid_types<quantity>);
|
||||
|
||||
#endif
|
||||
|
||||
static_assert(std::is_trivially_default_constructible_v<quantity<isq::length[m]>>);
|
||||
static_assert(std::is_trivially_copy_constructible_v<quantity<isq::length[m]>>);
|
||||
static_assert(std::is_trivially_move_constructible_v<quantity<isq::length[m]>>);
|
||||
|
Reference in New Issue
Block a user