Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: CPOs refactored to be more constrained #649

Merged
merged 7 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions example/include/ranged_representation.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ class ranged_representation : public validated_type<T, is_in_range_t<T, Min, Max
}
};

template<typename T, auto Min, auto Max>
constexpr bool mp_units::is_scalar<ranged_representation<T, Min, Max>> = mp_units::is_scalar<T>;

template<typename T, auto Min, auto Max, typename Char>
struct MP_UNITS_STD_FMT::formatter<ranged_representation<T, Min, Max>, Char> : formatter<T, Char> {
template<typename FormatContext>
Expand Down
3 changes: 0 additions & 3 deletions example/include/validated_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,6 @@ class validated_type {
= default;
};

template<typename T, typename Validator>
constexpr bool mp_units::is_scalar<validated_type<T, Validator>> = mp_units::is_scalar<T>;


template<typename CharT, typename Traits, typename T, typename Validator>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
Expand Down
4 changes: 0 additions & 4 deletions example/kalman_filter/kalman_filter-example_2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ import mp_units;

// Based on: https://www.kalmanfilter.net/alphabeta.html#ex2

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

using namespace mp_units;

void print_header(const kalman::SystemState auto& initial)
Expand Down
4 changes: 0 additions & 4 deletions example/kalman_filter/kalman_filter-example_3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ import mp_units;

// Based on: https://www.kalmanfilter.net/alphabeta.html#ex3

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

using namespace mp_units;

void print_header(const kalman::SystemState auto& initial)
Expand Down
4 changes: 0 additions & 4 deletions example/kalman_filter/kalman_filter-example_4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ import mp_units;

// Based on: https://www.kalmanfilter.net/alphabeta.html#ex4

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

using namespace mp_units;

void print_header(const kalman::SystemState auto& initial)
Expand Down
13 changes: 8 additions & 5 deletions example/measurement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,19 +124,22 @@ 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_{};
};

} // namespace

template<typename T>
constexpr bool mp_units::is_scalar<measurement<T>> = true;
template<typename T>
constexpr bool mp_units::is_vector<measurement<T>> = true;

static_assert(mp_units::RepresentationOf<measurement<double>, mp_units::quantity_character::scalar>);
static_assert(mp_units::RepresentationOf<measurement<double>, mp_units::quantity_character::vector>);

namespace {

Expand Down
6 changes: 0 additions & 6 deletions example/storage_tank.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ import mp_units;
#include <mp-units/systems/si.h>
#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<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

namespace {

using namespace mp_units;
Expand Down
4 changes: 0 additions & 4 deletions example/strong_angular_quantities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ import mp_units;
#include <mp-units/systems/si.h>
#endif

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

int main()
{
using namespace mp_units;
Expand Down
4 changes: 0 additions & 4 deletions example/total_energy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ import mp_units;
#include <mp-units/systems/si.h>
#endif

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

namespace {

using namespace mp_units;
Expand Down
5 changes: 1 addition & 4 deletions src/core/include/mp-units/cartesian_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>
{
return vec.magnitude();
Expand Down Expand Up @@ -263,9 +263,6 @@ template<typename Arg, typename... Args>
requires(sizeof...(Args) <= 2) && requires { typename std::common_type_t<Arg, Args...>; }
cartesian_vector(Arg, Args...) -> cartesian_vector<std::common_type_t<Arg, Args...>>;

template<class T>
constexpr bool is_vector<cartesian_vector<T>> = true;

} // namespace mp_units

#if MP_UNITS_HOSTED
Expand Down
6 changes: 3 additions & 3 deletions src/core/include/mp-units/complex.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <mp-units/bits/requires_hosted.h>
//
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/representation_concepts.h>

#ifndef MP_UNITS_IN_MODULE_INTERFACE
#ifdef MP_UNITS_IMPORT_STD
Expand All @@ -38,6 +38,6 @@ import std;
namespace mp_units {

template<typename T>
constexpr bool is_complex<std::complex<T>> = true;
constexpr bool disable_scalar<std::complex<T>> = true;

}
} // namespace mp_units
145 changes: 5 additions & 140 deletions src/core/include/mp-units/framework/customization_points.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,157 +60,22 @@ constexpr bool treat_as_floating_point =
std::is_floating_point_v<value_type_t<Rep>>;
#endif

/**
* @brief Specifies a type to have a scalar character
*
* A scalar is a physical quantity that has magnitude but no direction.
*/
template<typename Rep>
constexpr bool is_scalar = std::is_floating_point_v<Rep> || (std::is_integral_v<Rep> && !is_same_v<Rep, bool>);
[[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<typename Rep>
[[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<class T>
* requires mp_units::is_scalar<T>
* constexpr bool mp_units::is_vector<T> = true;
* @endcode
*/
template<typename Rep>
[[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<typename Rep>
[[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<typename T>
[[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<T>)
// 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<typename T>
[[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<typename T>
[[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<typename T>
[[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
*
Expand Down
4 changes: 4 additions & 0 deletions src/core/include/mp-units/framework/quantity_concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ template<typename T>
constexpr bool is_derived_from_specialization_of_quantity =
requires(T* type) { to_base_specialization_of_quantity(type); };

template<typename T>
requires is_derived_from_specialization_of_quantity<T>
constexpr bool is_quantity<T> = true;

} // namespace detail

/**
Expand Down
Loading
Loading