forked from mpusz/mp-units
refactor: derived_dimension
can now store only powers of base dimensions
This commit is contained in:
@@ -27,22 +27,36 @@ namespace units::isq {
|
|||||||
|
|
||||||
inline constexpr struct dim_length : base_dimension<"L"> {
|
inline constexpr struct dim_length : base_dimension<"L"> {
|
||||||
} dim_length;
|
} dim_length;
|
||||||
|
inline constexpr struct dim_mass : base_dimension<"M"> {
|
||||||
|
} dim_mass;
|
||||||
|
inline constexpr struct dim_time : base_dimension<"T"> {
|
||||||
|
} dim_time;
|
||||||
|
inline constexpr struct dim_electric_current : base_dimension<"I"> {
|
||||||
|
} dim_electric_current;
|
||||||
|
// TODO Should the below use basic_symbol_text? How to name it for ASCII?
|
||||||
|
inline constexpr struct dim_thermodynamic_temperature : base_dimension<"Θ"> {
|
||||||
|
} dim_thermodynamic_temperature;
|
||||||
|
inline constexpr struct dim_amount_of_substance : base_dimension<"N"> {
|
||||||
|
} dim_amount_of_substance;
|
||||||
|
inline constexpr struct dim_luminous_intensity : base_dimension<"J"> {
|
||||||
|
} dim_luminous_intensity;
|
||||||
|
|
||||||
|
// using dim_speed = decltype(dim_length / dim_time);
|
||||||
|
// inline constexpr dim_speed dim_speed;
|
||||||
|
|
||||||
// template<typename T>
|
// template<typename T>
|
||||||
// concept Length = QuantityOf<T, dim_length>;
|
// concept Length = QuantityOf<T, dim_length>;
|
||||||
|
|
||||||
inline constexpr struct dim_time : base_dimension<"T"> {
|
// inline constexpr struct dim_frequency : decltype(1 / dim_time) {
|
||||||
} dim_time;
|
// } dim_frequency;
|
||||||
inline constexpr struct dim_frequency : decltype(1 / dim_time) {
|
// inline constexpr struct dim_area : decltype(dim_length * dim_length) {
|
||||||
} dim_frequency;
|
// } dim_area;
|
||||||
inline constexpr struct dim_area : decltype(dim_length * dim_length) {
|
// inline constexpr struct dim_volume : decltype(dim_area * dim_length) {
|
||||||
} dim_area;
|
// } dim_volume;
|
||||||
inline constexpr struct dim_volume : decltype(dim_area * dim_length) {
|
// inline constexpr struct dim_speed : decltype(dim_length / dim_time) {
|
||||||
} dim_volume;
|
// } dim_speed;
|
||||||
inline constexpr struct dim_speed : decltype(dim_length / dim_time) {
|
// inline constexpr struct dim_acceleration : decltype(dim_speed / dim_time) {
|
||||||
} dim_speed;
|
// } dim_acceleration;
|
||||||
inline constexpr struct dim_acceleration : decltype(dim_speed / dim_time) {
|
|
||||||
} dim_acceleration;
|
|
||||||
|
|
||||||
// inline constexpr auto speed = length / time;
|
// inline constexpr auto speed = length / time;
|
||||||
|
|
||||||
@@ -198,15 +212,21 @@ inline constexpr struct length : system_reference<length, dim_length, metre> {
|
|||||||
} length;
|
} length;
|
||||||
inline constexpr struct time : system_reference<time, dim_time, second> {
|
inline constexpr struct time : system_reference<time, dim_time, second> {
|
||||||
} time;
|
} time;
|
||||||
inline constexpr struct frequency : system_reference<frequency, dim_frequency, hertz> {
|
// inline constexpr struct frequency : system_reference<frequency, dim_frequency, hertz> {
|
||||||
|
inline constexpr struct frequency : system_reference<frequency, 1 / dim_time, hertz> {
|
||||||
} frequency;
|
} frequency;
|
||||||
inline constexpr struct area : system_reference<area, dim_area, square_metre> {
|
// inline constexpr struct area : system_reference<area, dim_area, square_metre> {
|
||||||
|
inline constexpr struct area : system_reference<area, dim_length * dim_length, square_metre> {
|
||||||
} area;
|
} area;
|
||||||
inline constexpr struct volume : system_reference<volume, dim_volume, cubic_metre> {
|
// inline constexpr struct volume : system_reference<volume, dim_volume, cubic_metre> {
|
||||||
|
inline constexpr struct volume : system_reference<volume, dim_length * dim_length * dim_length, cubic_metre> {
|
||||||
} volume;
|
} volume;
|
||||||
inline constexpr struct speed : system_reference<speed, dim_speed, metre / second> {
|
// inline constexpr struct speed : system_reference<speed, dim_speed, metre / second> {
|
||||||
|
inline constexpr struct speed : system_reference<speed, dim_length / dim_time, metre / second> {
|
||||||
} speed;
|
} speed;
|
||||||
inline constexpr struct acceleration : system_reference<acceleration, dim_acceleration, metre / second / second> {
|
// inline constexpr struct acceleration : system_reference<acceleration, dim_acceleration, metre / second / second> {
|
||||||
|
inline constexpr struct acceleration :
|
||||||
|
system_reference<acceleration, dim_length / (dim_time * dim_time), metre / (second * second)> {
|
||||||
} acceleration;
|
} acceleration;
|
||||||
|
|
||||||
} // namespace units::isq::si
|
} // namespace units::isq::si
|
||||||
@@ -257,47 +277,51 @@ static_assert(is_of_type<dim_length / dim_time*(dim_length / dim_time),
|
|||||||
derived_dimension<power<struct dim_length, 2>, per<power<struct dim_time, 2>>>>);
|
derived_dimension<power<struct dim_length, 2>, per<power<struct dim_time, 2>>>>);
|
||||||
static_assert(is_of_type<dim_length / dim_time*(dim_time / dim_length), struct dim_one>);
|
static_assert(is_of_type<dim_length / dim_time*(dim_time / dim_length), struct dim_one>);
|
||||||
|
|
||||||
static_assert(
|
// static_assert(
|
||||||
is_of_type<dim_speed / dim_acceleration, derived_dimension<struct dim_speed, per<struct dim_acceleration>>>);
|
// is_of_type<dim_speed / dim_acceleration, derived_dimension<struct dim_speed, per<struct dim_acceleration>>>);
|
||||||
static_assert(
|
// static_assert(
|
||||||
is_of_type<dim_acceleration / dim_speed, derived_dimension<struct dim_acceleration, per<struct dim_speed>>>);
|
// is_of_type<dim_acceleration / dim_speed, derived_dimension<struct dim_acceleration, per<struct dim_speed>>>);
|
||||||
static_assert(is_of_type<dim_speed * dim_speed / dim_length,
|
// static_assert(is_of_type<dim_speed * dim_speed / dim_length,
|
||||||
derived_dimension<power<struct dim_speed, 2>, per<struct dim_length>>>);
|
// derived_dimension<power<struct dim_speed, 2>, per<struct dim_length>>>);
|
||||||
static_assert(is_of_type<1 / (dim_speed * dim_speed) * dim_length,
|
// static_assert(is_of_type<1 / (dim_speed * dim_speed) * dim_length,
|
||||||
derived_dimension<struct dim_length, per<power<struct dim_speed, 2>>>>);
|
// derived_dimension<struct dim_length, per<power<struct dim_speed, 2>>>>);
|
||||||
|
|
||||||
|
namespace si {
|
||||||
|
|
||||||
// comparisons of equivalent dimensions
|
// comparisons of equivalent dimensions
|
||||||
static_assert(dim_length / dim_length == dim_one);
|
static_assert(dim_length / dim_length == dim_one);
|
||||||
|
|
||||||
static_assert(1 / dim_time == dim_frequency);
|
static_assert(1 / dim_time == frequency::dimension);
|
||||||
static_assert(1 / dim_frequency == dim_time);
|
static_assert(1 / frequency::dimension == dim_time);
|
||||||
static_assert(dim_frequency * dim_time == dim_one);
|
static_assert(frequency::dimension * dim_time == dim_one);
|
||||||
|
|
||||||
static_assert(dim_length * dim_length == dim_area);
|
static_assert(dim_length * dim_length == area::dimension);
|
||||||
static_assert(dim_length * dim_length != dim_volume);
|
static_assert(dim_length * dim_length != volume::dimension);
|
||||||
static_assert(dim_area / dim_length == dim_length);
|
static_assert(area::dimension / dim_length == dim_length);
|
||||||
|
|
||||||
static_assert(dim_length * dim_length * dim_length == dim_volume);
|
static_assert(dim_length * dim_length * dim_length == volume::dimension);
|
||||||
static_assert(dim_area * dim_length == dim_volume);
|
static_assert(area::dimension * dim_length == volume::dimension);
|
||||||
static_assert(dim_volume / dim_length == dim_area);
|
static_assert(volume::dimension / dim_length == area::dimension);
|
||||||
static_assert(dim_volume / dim_length / dim_length == dim_length);
|
static_assert(volume::dimension / dim_length / dim_length == dim_length);
|
||||||
static_assert(dim_area * dim_area / dim_length == dim_volume);
|
static_assert(area::dimension * area::dimension / dim_length == volume::dimension);
|
||||||
static_assert(dim_area * (dim_area / dim_length) == dim_volume);
|
static_assert(area::dimension * (area::dimension / dim_length) == volume::dimension);
|
||||||
static_assert(dim_volume / (dim_length * dim_length) == dim_length);
|
static_assert(volume::dimension / (dim_length * dim_length) == dim_length);
|
||||||
|
|
||||||
static_assert(dim_length / dim_time == dim_speed);
|
static_assert(dim_length / dim_time == speed::dimension);
|
||||||
static_assert(dim_length * dim_time != dim_speed);
|
static_assert(dim_length * dim_time != speed::dimension);
|
||||||
static_assert(dim_length / dim_time / dim_time != dim_speed);
|
static_assert(dim_length / dim_time / dim_time != speed::dimension);
|
||||||
static_assert(dim_length / dim_speed == dim_time);
|
static_assert(dim_length / speed::dimension == dim_time);
|
||||||
static_assert(dim_speed * dim_time == dim_length);
|
static_assert(speed::dimension * dim_time == dim_length);
|
||||||
|
|
||||||
static_assert(dim_length / dim_time / dim_time == dim_acceleration);
|
static_assert(dim_length / dim_time / dim_time == acceleration::dimension);
|
||||||
static_assert(dim_length / (dim_time * dim_time) == dim_acceleration);
|
static_assert(dim_length / (dim_time * dim_time) == acceleration::dimension);
|
||||||
static_assert(dim_speed / dim_time == dim_acceleration);
|
static_assert(speed::dimension / dim_time == acceleration::dimension);
|
||||||
static_assert(dim_speed / dim_acceleration == dim_time);
|
static_assert(speed::dimension / acceleration::dimension == dim_time);
|
||||||
static_assert(dim_acceleration * dim_time == dim_speed);
|
static_assert(acceleration::dimension * dim_time == speed::dimension);
|
||||||
static_assert(dim_acceleration * (dim_time * dim_time) == dim_length);
|
static_assert(acceleration::dimension * (dim_time * dim_time) == dim_length);
|
||||||
static_assert(dim_acceleration / dim_speed == dim_frequency);
|
static_assert(acceleration::dimension / speed::dimension == frequency::dimension);
|
||||||
|
|
||||||
|
} // namespace si
|
||||||
|
|
||||||
} // namespace units::isq
|
} // namespace units::isq
|
||||||
|
|
||||||
@@ -344,35 +368,35 @@ static_assert(is_of_type<joule / watt, derived_unit<struct joule, per<struct wat
|
|||||||
// comparisons of equivalent dimensions
|
// comparisons of equivalent dimensions
|
||||||
// static_assert(metre / metre == one);
|
// static_assert(metre / metre == one);
|
||||||
|
|
||||||
// static_assert(1 / second == dim_frequency);
|
// static_assert(1 / second == frequency::dimension);
|
||||||
// static_assert(1 / dim_frequency == second);
|
// static_assert(1 / frequency::dimension == second);
|
||||||
// static_assert(dim_frequency * second == one);
|
// static_assert(frequency::dimension * second == one);
|
||||||
|
|
||||||
// static_assert(metre * metre == dim_area);
|
// static_assert(metre * metre == area::dimension);
|
||||||
// static_assert(metre * metre != dim_volume);
|
// static_assert(metre * metre != volume::dimension);
|
||||||
// static_assert(dim_area / metre == metre);
|
// static_assert(area::dimension / metre == metre);
|
||||||
|
|
||||||
// static_assert(metre * metre * metre == dim_volume);
|
// static_assert(metre * metre * metre == volume::dimension);
|
||||||
// static_assert(dim_area * metre == dim_volume);
|
// static_assert(area::dimension * metre == volume::dimension);
|
||||||
// static_assert(dim_volume / metre == dim_area);
|
// static_assert(volume::dimension / metre == area::dimension);
|
||||||
// static_assert(dim_volume / metre / metre == metre);
|
// static_assert(volume::dimension / metre / metre == metre);
|
||||||
// static_assert(dim_area * dim_area / metre == dim_volume);
|
// static_assert(area::dimension * area::dimension / metre == volume::dimension);
|
||||||
// static_assert(dim_area * (dim_area / metre) == dim_volume);
|
// static_assert(area::dimension * (area::dimension / metre) == volume::dimension);
|
||||||
// static_assert(dim_volume / (metre * metre) == metre);
|
// static_assert(volume::dimension / (metre * metre) == metre);
|
||||||
|
|
||||||
// static_assert(metre / second == dim_speed);
|
// static_assert(metre / second == speed::dimension);
|
||||||
// static_assert(metre * second != dim_speed);
|
// static_assert(metre * second != speed::dimension);
|
||||||
// static_assert(metre / second / second != dim_speed);
|
// static_assert(metre / second / second != speed::dimension);
|
||||||
// static_assert(metre / dim_speed == second);
|
// static_assert(metre / speed::dimension == second);
|
||||||
// static_assert(dim_speed * second == metre);
|
// static_assert(speed::dimension * second == metre);
|
||||||
|
|
||||||
// static_assert(metre / second / second == dim_acceleration);
|
// static_assert(metre / second / second == acceleration::dimension);
|
||||||
// static_assert(metre / (second * second) == dim_acceleration);
|
// static_assert(metre / (second * second) == acceleration::dimension);
|
||||||
// static_assert(dim_speed / second == dim_acceleration);
|
// static_assert(speed::dimension / second == acceleration::dimension);
|
||||||
// static_assert(dim_speed / dim_acceleration == second);
|
// static_assert(speed::dimension / acceleration::dimension == second);
|
||||||
// static_assert(dim_acceleration * second == dim_speed);
|
// static_assert(acceleration::dimension * second == speed::dimension);
|
||||||
// static_assert(dim_acceleration * (second * second) == metre);
|
// static_assert(acceleration::dimension * (second * second) == metre);
|
||||||
// static_assert(dim_acceleration / dim_speed == dim_frequency);
|
// static_assert(acceleration::dimension / speed::dimension == frequency::dimension);
|
||||||
|
|
||||||
|
|
||||||
// Bq + Hz should not compile
|
// Bq + Hz should not compile
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <units/bits/expression_template.h>
|
#include <units/bits/expression_template.h>
|
||||||
#include <units/bits/external/fixed_string.h>
|
#include <units/bits/external/fixed_string.h>
|
||||||
#include <units/bits/external/type_name.h>
|
|
||||||
#include <units/bits/external/type_traits.h>
|
#include <units/bits/external/type_traits.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -87,99 +86,24 @@ concept Dimension = BaseDimension<T> || DerivedDimension<T>;
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unpacks the list of potentially derived dimensions to a list containing only base dimensions
|
|
||||||
*
|
|
||||||
* @tparam Es Exponents of potentially derived dimensions
|
|
||||||
*/
|
|
||||||
template<typename NumList, typename DenList>
|
|
||||||
struct dim_extract;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct dim_extract<type_list<>, type_list<>> {
|
|
||||||
using num = type_list<>;
|
|
||||||
using den = type_list<>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename... NRest, typename... Dens>
|
|
||||||
requires BaseDimension<T> || BaseDimension<typename T::factor>
|
|
||||||
struct dim_extract<type_list<T, NRest...>, type_list<Dens...>> {
|
|
||||||
using impl = dim_extract<type_list<NRest...>, type_list<Dens...>>;
|
|
||||||
using num = type_list_push_front<typename impl::num, T>;
|
|
||||||
using den = TYPENAME impl::den;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename... DRest>
|
|
||||||
requires BaseDimension<T> || BaseDimension<typename T::factor>
|
|
||||||
struct dim_extract<type_list<>, type_list<T, DRest...>> {
|
|
||||||
using impl = dim_extract<type_list<>, type_list<DRest...>>;
|
|
||||||
using num = TYPENAME impl::num;
|
|
||||||
using den = type_list_push_front<typename impl::den, T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<DerivedDimension T, typename... NRest, typename... Dens>
|
|
||||||
struct dim_extract<type_list<T, NRest...>, type_list<Dens...>> :
|
|
||||||
dim_extract<type_list_push_back<typename T::normalized_num, NRest...>,
|
|
||||||
type_list_push_back<typename T::normalized_den, Dens...>> {};
|
|
||||||
|
|
||||||
template<DerivedDimension T, int... Ints, typename... NRest, typename... Dens>
|
|
||||||
struct dim_extract<type_list<power<T, Ints...>, NRest...>, type_list<Dens...>> :
|
|
||||||
dim_extract<type_list_push_back<
|
|
||||||
typename expr_power<typename T::normalized_num, power<T, Ints...>::num, power<T, Ints...>::den>::type,
|
|
||||||
NRest...>,
|
|
||||||
type_list_push_back<
|
|
||||||
typename expr_power<typename T::normalized_den, power<T, Ints...>::num, power<T, Ints...>::den>::type,
|
|
||||||
Dens...>> {};
|
|
||||||
|
|
||||||
|
|
||||||
template<DerivedDimension T, typename... DRest>
|
|
||||||
struct dim_extract<type_list<>, type_list<T, DRest...>> :
|
|
||||||
dim_extract<typename T::normalized_den, type_list_push_back<typename T::normalized_num, DRest...>> {};
|
|
||||||
|
|
||||||
template<DerivedDimension T, int... Ints, typename... DRest>
|
|
||||||
struct dim_extract<type_list<>, type_list<power<T, Ints...>, DRest...>> :
|
|
||||||
dim_extract<typename expr_power<typename T::normalized_den, power<T, Ints...>::num, power<T, Ints...>::den>::type,
|
|
||||||
type_list_push_back<
|
|
||||||
typename expr_power<typename T::normalized_num, power<T, Ints...>::num, power<T, Ints...>::den>::type,
|
|
||||||
DRest...>> {};
|
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
|
using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
|
||||||
|
|
||||||
/**
|
template<typename T>
|
||||||
* @brief Converts user provided derived dimension specification into a valid units::normalized_dimension definition
|
inline constexpr bool is_dim_one = false;
|
||||||
*
|
|
||||||
* User provided definition of a derived dimension may contain the same base dimension repeated more than once on the
|
|
||||||
* list possibly hidden in other derived units provided by the user. The process here should:
|
|
||||||
* 1. Extract derived dimensions into exponents of base dimensions.
|
|
||||||
* 2. Sort the exponents so the same dimensions are placed next to each other.
|
|
||||||
* 3. Consolidate contiguous range of exponents of the same base dimensions to a one (or possibly zero) exponent for
|
|
||||||
* this base dimension.
|
|
||||||
*/
|
|
||||||
template<typename OneTypeBase, typename... Ds>
|
|
||||||
struct normalized_dimension : detail::expr_fractions<OneTypeBase, Ds...> {
|
|
||||||
private:
|
|
||||||
using base = detail::expr_fractions<OneTypeBase, Ds...>;
|
|
||||||
using extracted = dim_extract<typename base::num, typename base::den>;
|
|
||||||
using num_list = expr_consolidate<type_list_sort<typename extracted::num, type_list_of_base_dimension_less>>;
|
|
||||||
using den_list = expr_consolidate<type_list_sort<typename extracted::den, type_list_of_base_dimension_less>>;
|
|
||||||
using simple = expr_simplify<num_list, den_list, type_list_of_base_dimension_less>;
|
|
||||||
public:
|
|
||||||
using normalized_num = TYPENAME simple::num;
|
|
||||||
using normalized_den = TYPENAME simple::den;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
// TODO add checking for `per` and power elements as well
|
// TODO add checking for `per` and power elements as well
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept DimensionSpec = Dimension<T> || is_specialization_of<T, per> || detail::is_specialization_of_power<T>;
|
concept DimensionSpec =
|
||||||
|
BaseDimension<T> || detail::is_dim_one<T> || is_specialization_of<T, per> || detail::is_specialization_of_power<T>;
|
||||||
|
|
||||||
// User should not instantiate this type!!!
|
// User should not instantiate this type!!!
|
||||||
|
// It should not be exported from the module
|
||||||
template<DimensionSpec... Ds>
|
template<DimensionSpec... Ds>
|
||||||
struct derived_dimension : detail::normalized_dimension<derived_dimension<>, Ds...> {};
|
struct derived_dimension : detail::expr_fractions<derived_dimension<>, Ds...> {};
|
||||||
|
|
||||||
// TODO move type_list_fractions out of
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
std::true_type is_derived_dimension(const volatile derived_dimension<Args...>*);
|
std::true_type is_derived_dimension(const volatile derived_dimension<Args...>*);
|
||||||
@@ -195,66 +119,42 @@ inline constexpr struct dim_one : derived_dimension<> {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<>
|
||||||
struct dimension_less : std::bool_constant<type_name<D1>() < type_name<D2>()> {};
|
inline constexpr bool is_dim_one<struct dim_one> = true;
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
using type_list_of_dimension_less = expr_less<T1, T2, dimension_less>;
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
constexpr Dimension auto operator*(D1, D2)
|
[[nodiscard]] constexpr Dimension auto operator*(D1, D2)
|
||||||
{
|
{
|
||||||
return detail::expr_multiply<D1, D2, struct dim_one, detail::type_list_of_dimension_less, derived_dimension>();
|
return detail::expr_multiply<D1, D2, struct dim_one, detail::type_list_of_base_dimension_less, derived_dimension>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
constexpr Dimension auto operator/(D1, D2)
|
[[nodiscard]] constexpr Dimension auto operator/(D1, D2)
|
||||||
{
|
{
|
||||||
return detail::expr_divide<D1, D2, struct dim_one, detail::type_list_of_dimension_less, derived_dimension>();
|
return detail::expr_divide<D1, D2, struct dim_one, detail::type_list_of_base_dimension_less, derived_dimension>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D>
|
template<Dimension D>
|
||||||
constexpr Dimension auto operator/(int value, D)
|
[[nodiscard]] constexpr Dimension auto operator/(int value, D)
|
||||||
{
|
{
|
||||||
gsl_Assert(value == 1);
|
gsl_Assert(value == 1);
|
||||||
return detail::expr_invert<D, struct dim_one, derived_dimension>();
|
return detail::expr_invert<D, struct dim_one, derived_dimension>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
constexpr bool operator==(D1, D2)
|
[[nodiscard]] constexpr bool operator==(D1, D2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<BaseDimension D1, BaseDimension D2>
|
template<Dimension D>
|
||||||
constexpr bool operator==(D1, D2)
|
[[nodiscard]] constexpr bool operator==(D, D)
|
||||||
{
|
{
|
||||||
return D1::symbol == D2::symbol;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<BaseDimension D1, Dimension D2>
|
// TODO consider adding the support for text output of the dimensional equation
|
||||||
requires(type_list_size<typename D2::normalized_den> == 0) && (type_list_size<typename D2::normalized_num> == 1) &&
|
|
||||||
BaseDimension<type_list_front<typename D2::normalized_num>>
|
|
||||||
constexpr bool operator==(D1, D2)
|
|
||||||
{
|
|
||||||
return D1::symbol == type_list_front<typename D2::normalized_num>::symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Dimension D1, BaseDimension D2>
|
|
||||||
requires(type_list_size<typename D1::normalized_den> == 0) && (type_list_size<typename D1::normalized_num> == 1) &&
|
|
||||||
BaseDimension<type_list_front<typename D1::normalized_num>>
|
|
||||||
constexpr bool operator==(D1, D2)
|
|
||||||
{
|
|
||||||
return type_list_front<typename D1::normalized_num>::symbol == D2::symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<DerivedDimension D1, DerivedDimension D2>
|
|
||||||
constexpr bool operator==(D1, D2)
|
|
||||||
{
|
|
||||||
return is_same_v<typename D1::normalized_num, typename D2::normalized_num> &&
|
|
||||||
is_same_v<typename D1::normalized_den, typename D2::normalized_den>;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
Reference in New Issue
Block a user