forked from mpusz/mp-units
Merge branch 'master' into chiphogg/switch-to-mag
This commit is contained in:
+28
-2
@@ -20,7 +20,7 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
# core library options
|
||||
set(${projectPrefix}DOWNCAST_MODE ON CACHE STRING "Select downcasting mode")
|
||||
@@ -34,7 +34,33 @@ include(CheckLibcxxInUse)
|
||||
check_libcxx_in_use(${projectPrefix}LIBCXX)
|
||||
|
||||
# core library definition
|
||||
add_library(mp-units-core INTERFACE)
|
||||
add_library(
|
||||
mp-units-core
|
||||
INTERFACE
|
||||
include/units/base_dimension.h
|
||||
include/units/chrono.h
|
||||
include/units/concepts.h
|
||||
include/units/customization_points.h
|
||||
include/units/derived_dimension.h
|
||||
include/units/exponent.h
|
||||
include/units/generic/angle.h
|
||||
include/units/generic/dimensionless.h
|
||||
include/units/kind.h
|
||||
include/units/magnitude.h
|
||||
include/units/math.h
|
||||
include/units/point_origin.h
|
||||
include/units/prefix.h
|
||||
include/units/quantity.h
|
||||
include/units/quantity_cast.h
|
||||
include/units/quantity_kind.h
|
||||
include/units/quantity_point.h
|
||||
include/units/quantity_point_kind.h
|
||||
include/units/random.h
|
||||
include/units/ratio.h
|
||||
include/units/reference.h
|
||||
include/units/symbol_text.h
|
||||
include/units/unit.h
|
||||
)
|
||||
target_compile_features(mp-units-core INTERFACE cxx_std_20)
|
||||
target_link_libraries(mp-units-core INTERFACE gsl::gsl-lite)
|
||||
target_include_directories(
|
||||
|
||||
@@ -50,8 +50,7 @@ namespace units {
|
||||
* @tparam Symbol an unique identifier of the base dimension used to provide dimensional analysis support
|
||||
* @tparam U a base unit to be used for this base dimension
|
||||
*/
|
||||
template<basic_fixed_string Symbol, Unit U>
|
||||
requires U::is_named
|
||||
template<basic_fixed_string Symbol, NamedUnit U>
|
||||
struct base_dimension {
|
||||
static constexpr auto symbol = Symbol; ///< Unique base dimension identifier
|
||||
using base_unit = U; ///< Base unit adopted for this dimension
|
||||
|
||||
@@ -37,25 +37,14 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
// PrefixFamily
|
||||
struct prefix_family;
|
||||
|
||||
/**
|
||||
* @brief A concept matching a prefix family
|
||||
*
|
||||
* Satisfied by all types derived from `prefix_family`
|
||||
*/
|
||||
template<typename T>
|
||||
concept PrefixFamily = std::derived_from<T, prefix_family>;
|
||||
|
||||
// Prefix
|
||||
namespace detail {
|
||||
|
||||
template<PrefixFamily PF, ratio R>
|
||||
template<ratio R>
|
||||
struct prefix_base;
|
||||
|
||||
template<PrefixFamily PF, ratio R>
|
||||
void to_prefix_base(const volatile prefix_base<PF, R>*);
|
||||
template<ratio R>
|
||||
void to_prefix_base(const volatile prefix_base<R>*);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -87,9 +76,18 @@ void to_base_scaled_unit(const volatile scaled_unit<M, U>*);
|
||||
template<typename T>
|
||||
concept Unit = requires(T* t) { detail::to_base_scaled_unit(t); };
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename>
|
||||
inline constexpr bool is_named = false;
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
concept NamedUnit = Unit<T> && detail::is_named<T>;
|
||||
|
||||
// BaseDimension
|
||||
template<basic_fixed_string Symbol, Unit U>
|
||||
requires U::is_named
|
||||
template<basic_fixed_string Symbol, NamedUnit U>
|
||||
struct base_dimension;
|
||||
|
||||
namespace detail {
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ inline constexpr bool same_scaled_units = false;
|
||||
template<typename... Es, Unit... Us>
|
||||
inline constexpr bool same_scaled_units<exponent_list<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
|
||||
|
||||
// derived_unit
|
||||
// derived_scaled_unit
|
||||
|
||||
template<Unit... Us, typename... Es>
|
||||
constexpr Magnitude auto derived_mag(exponent_list<Es...>)
|
||||
@@ -44,6 +44,6 @@ constexpr Magnitude auto derived_mag(exponent_list<Es...>)
|
||||
}
|
||||
|
||||
template<DerivedDimension D, Unit... Us>
|
||||
using derived_unit = scaled_unit<derived_mag<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
|
||||
using derived_scaled_unit = scaled_unit<derived_mag<Us...>(typename D::recipe()), typename D::coherent_unit::reference>;
|
||||
|
||||
} // namespace units::detail
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <units/bits/external/text_tools.h>
|
||||
#include <units/derived_dimension.h>
|
||||
#include <units/prefix.h>
|
||||
#include <units/unit.h>
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
@@ -57,28 +58,19 @@ constexpr auto ratio_text()
|
||||
}
|
||||
}
|
||||
|
||||
template<ratio R, typename PrefixFamily, std::size_t SymbolLen>
|
||||
template<Unit U, ratio R, std::size_t SymbolLen>
|
||||
constexpr auto prefix_or_ratio_text()
|
||||
{
|
||||
if constexpr (R.num == 1 && R.den == 1 && R.exp == 0) {
|
||||
// no ratio/prefix
|
||||
return basic_fixed_string("");
|
||||
} else {
|
||||
if constexpr (!is_same_v<PrefixFamily, no_prefix>) {
|
||||
// try to form a prefix
|
||||
using prefix = downcast<detail::prefix_base<PrefixFamily, R>>;
|
||||
// try to form a prefix
|
||||
using prefix = downcast<detail::prefix_base<R>>;
|
||||
|
||||
if constexpr (!is_same_v<prefix, prefix_base<PrefixFamily, R>>) {
|
||||
// print as a prefixed unit
|
||||
return prefix::symbol;
|
||||
} else {
|
||||
// print as a ratio of the coherent unit
|
||||
constexpr auto txt = ratio_text<R>();
|
||||
if constexpr (SymbolLen > 0 && txt.standard().size() > 0)
|
||||
return txt + basic_fixed_string(" ");
|
||||
else
|
||||
return txt;
|
||||
}
|
||||
if constexpr (can_be_prefixed<U> && !is_same_v<prefix, prefix_base<R>>) {
|
||||
// print as a prefixed unit
|
||||
return prefix::symbol;
|
||||
} else {
|
||||
// print as a ratio of the coherent unit
|
||||
constexpr auto txt = ratio_text<R>();
|
||||
@@ -110,7 +102,7 @@ template<Exponent Exp>
|
||||
constexpr auto exponent_list_with_named_units(Exp)
|
||||
{
|
||||
using dim = TYPENAME Exp::dimension;
|
||||
if constexpr (dimension_unit<dim>::is_named) {
|
||||
if constexpr (NamedUnit<dimension_unit<dim>>) {
|
||||
return exponent_list<Exp>();
|
||||
} else {
|
||||
using recipe = TYPENAME dim::recipe;
|
||||
@@ -147,21 +139,16 @@ constexpr auto unit_text()
|
||||
// print as a prefix or ratio of a coherent unit
|
||||
using coherent_unit = dimension_unit<Dim>;
|
||||
|
||||
if constexpr (has_symbol<coherent_unit>) {
|
||||
// use predefined coherent unit symbol
|
||||
constexpr auto symbol_text = coherent_unit::symbol;
|
||||
constexpr auto prefix_txt =
|
||||
prefix_or_ratio_text<as_ratio(U::mag / coherent_unit::mag), typename U::reference::prefix_family,
|
||||
symbol_text.standard().size()>();
|
||||
return prefix_txt + symbol_text;
|
||||
} else {
|
||||
// use derived dimension ingredients to create a unit symbol
|
||||
constexpr auto symbol_text = derived_dimension_unit_text<Dim>();
|
||||
constexpr auto prefix_txt =
|
||||
prefix_or_ratio_text<as_ratio(U::mag / coherent_unit::mag), typename U::reference::prefix_family,
|
||||
symbol_text.standard().size()>();
|
||||
return prefix_txt + symbol_text;
|
||||
}
|
||||
constexpr auto symbol_text = []() {
|
||||
if constexpr (has_symbol<coherent_unit>)
|
||||
return coherent_unit::symbol;
|
||||
else
|
||||
return derived_dimension_unit_text<Dim>();
|
||||
}();
|
||||
|
||||
constexpr auto prefix_txt =
|
||||
prefix_or_ratio_text<U, as_ratio(U::mag / coherent_unit::mag), symbol_text.standard().size()>();
|
||||
return prefix_txt + symbol_text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
struct radian : named_unit<radian, "rad", isq::si::prefix> {};
|
||||
struct radian : named_unit<radian, "rad"> {};
|
||||
|
||||
template<Unit U = radian>
|
||||
struct dim_angle : base_dimension<"A", U> {};
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
struct one : named_unit<one, "", no_prefix> {};
|
||||
struct percent : named_scaled_unit<percent, "%", no_prefix, as_magnitude<ratio(1, 100)>(), one> {};
|
||||
struct one : derived_unit<one> {};
|
||||
struct percent : named_scaled_unit<percent, "%", as_magnitude<ratio(1, 100)>(), one> {};
|
||||
|
||||
/**
|
||||
* @brief Dimension one
|
||||
|
||||
@@ -32,26 +32,10 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
/**
|
||||
* @brief The base for all prefix families
|
||||
*
|
||||
* Every prefix family should inherit from this type to satisfy PrefixFamily concept.
|
||||
*/
|
||||
struct prefix_family {};
|
||||
|
||||
/**
|
||||
* @brief No prefix possible for the unit
|
||||
*
|
||||
* This is a special prefix type tag specifying that the unit can not be scaled with any kind
|
||||
* of the prefix.
|
||||
*/
|
||||
struct no_prefix : prefix_family {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<PrefixFamily PF, ratio R>
|
||||
struct prefix_base : downcast_base<prefix_base<PF, R>> {
|
||||
using prefix_family = PF;
|
||||
template<ratio R>
|
||||
struct prefix_base : downcast_base<prefix_base<R>> {
|
||||
static constexpr Magnitude auto mag = as_magnitude<R>();
|
||||
};
|
||||
|
||||
@@ -64,17 +48,14 @@ struct prefix_base : downcast_base<prefix_base<PF, R>> {
|
||||
* - when defining a prefixed_unit its ratio is used to scale the reference unit and its
|
||||
* symbol is used to prepend to the symbol of referenced unit
|
||||
* - when printing the symbol of a scaled unit that was not predefined by the user but its
|
||||
* factor matches ratio of a prefix from the specified prefix family, its symbol will be
|
||||
* prepended to the symbol of the unit
|
||||
* factor matches ratio of a prefix, its symbol will be prepended to the symbol of the unit
|
||||
*
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
* @tparam PF a type of prefix family
|
||||
* @tparam Symbol a text representation of the prefix
|
||||
* @tparam R factor to be used to scale a unit
|
||||
*/
|
||||
template<typename Child, PrefixFamily PF, basic_symbol_text Symbol, ratio R>
|
||||
requires(!std::same_as<PF, no_prefix>)
|
||||
struct prefix : downcast_dispatch<Child, detail::prefix_base<PF, R>, downcast_mode::on> {
|
||||
template<typename Child, basic_symbol_text Symbol, ratio R>
|
||||
struct prefix : downcast_dispatch<Child, detail::prefix_base<R>, downcast_mode::on> {
|
||||
static constexpr auto symbol = Symbol;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,6 +45,12 @@ inline constexpr auto make_quantity = [](auto&& v) {
|
||||
return quantity<typename decltype(R)::dimension, typename decltype(R)::unit, Rep>(std::forward<decltype(v)>(v));
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept quantity_one =
|
||||
Quantity<T> &&
|
||||
(std::same_as<typename T::dimension, dim_one> || std::same_as<typename T::dimension, unknown_dimension<>>) &&
|
||||
detail::equivalent_unit<typename T::unit, typename T::dimension, ::units::one, typename T::dimension>::value;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
@@ -133,8 +139,7 @@ public:
|
||||
|
||||
template<typename Value>
|
||||
requires(safe_convertible_to_<std::remove_cvref_t<Value>, rep>)
|
||||
constexpr explicit(!(std::same_as<dimension, dim_one> && std::same_as<unit, ::units::one>)) quantity(Value&& v) :
|
||||
number_(std::forward<Value>(v))
|
||||
constexpr explicit(!detail::quantity_one<quantity>) quantity(Value&& v) : number_(std::forward<Value>(v))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -252,9 +257,9 @@ public:
|
||||
number_ *= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity& operator*=(const dimensionless<units::one, Rep2>& rhs)
|
||||
requires requires(rep a, const Rep2 b) {
|
||||
template<detail::quantity_one Q>
|
||||
constexpr quantity& operator*=(const Q& rhs)
|
||||
requires requires(rep a, const typename Q::rep b) {
|
||||
{
|
||||
a *= b
|
||||
} -> std::same_as<rep&>;
|
||||
@@ -276,15 +281,15 @@ public:
|
||||
number_ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity& operator/=(const dimensionless<units::one, Rep2>& rhs)
|
||||
requires requires(rep a, const Rep2 b) {
|
||||
template<detail::quantity_one Q>
|
||||
constexpr quantity& operator/=(const Q& rhs)
|
||||
requires requires(rep a, const typename Q::rep b) {
|
||||
{
|
||||
a /= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
{
|
||||
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
|
||||
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
|
||||
number_ /= rhs.number();
|
||||
return *this;
|
||||
}
|
||||
@@ -302,15 +307,15 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Rep2>
|
||||
constexpr quantity& operator%=(const dimensionless<units::one, Rep2>& rhs)
|
||||
requires(!floating_point_<rep>) && (!floating_point_<Rep2>) && requires(rep a, const Rep2 b) {
|
||||
{
|
||||
a %= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
template<detail::quantity_one Q>
|
||||
constexpr quantity& operator%=(const Q& rhs)
|
||||
requires(!floating_point_<rep>) && (!floating_point_<typename Q::rep>) && requires(rep a, const typename Q::rep b) {
|
||||
{
|
||||
a %= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
{
|
||||
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
|
||||
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
|
||||
number_ %= rhs.number();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ inline constexpr auto downcasted_kind_fn = [](auto q) {
|
||||
template<QuantityKind QK>
|
||||
inline constexpr auto& downcasted_kind = downcasted_kind_fn<typename QK::kind_type::base_kind>;
|
||||
|
||||
template<typename T, typename K>
|
||||
concept quantity_kind_one = QuantityKind<T> && equivalent<typename T::kind_type, downcast_kind<K, dim_one>> &&
|
||||
detail::quantity_one<typename T::quantity_type>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@@ -198,8 +202,8 @@ public:
|
||||
q_ *= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator*=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
|
||||
template<detail::quantity_kind_one<K> QK>
|
||||
constexpr quantity_kind& operator*=(const QK& rhs)
|
||||
requires requires(quantity_type q) { q *= rhs.common(); }
|
||||
{
|
||||
q_ *= rhs.common();
|
||||
@@ -214,8 +218,8 @@ public:
|
||||
q_ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
template<typename Rep2>
|
||||
constexpr quantity_kind& operator/=(const quantity_kind<downcast_kind<K, dim_one>, units::one, Rep2>& rhs)
|
||||
template<detail::quantity_kind_one<K> QK>
|
||||
constexpr quantity_kind& operator/=(const QK& rhs)
|
||||
requires requires(quantity_type q) { q /= rhs.common(); }
|
||||
{
|
||||
q_ /= rhs.common();
|
||||
@@ -233,8 +237,7 @@ public:
|
||||
|
||||
template<QuantityKind QK>
|
||||
constexpr quantity_kind& operator%=(const QK& rhs)
|
||||
requires(QuantityKindEquivalentTo<QK, quantity_kind> ||
|
||||
std::same_as<typename QK::kind_type, downcast_kind<K, dim_one>>) &&
|
||||
requires(QuantityKindEquivalentTo<QK, quantity_kind> || detail::quantity_kind_one<QK, K>) &&
|
||||
requires(quantity_type q) { q %= rhs.common(); }
|
||||
{
|
||||
gsl_ExpectsAudit(rhs.common().number() != quantity_values<typename QK::rep>::zero());
|
||||
|
||||
@@ -78,16 +78,16 @@ struct basic_symbol_text {
|
||||
{
|
||||
detail::validate_ascii_string<N>(std.data_);
|
||||
}
|
||||
constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&a)[M + 1]) noexcept :
|
||||
standard_(std), ascii_(a)
|
||||
constexpr basic_symbol_text(const StandardCharT (&std)[N + 1], const char (&ascii)[M + 1]) noexcept :
|
||||
standard_(std), ascii_(ascii)
|
||||
{
|
||||
detail::validate_ascii_string<M>(a);
|
||||
detail::validate_ascii_string<M>(ascii);
|
||||
}
|
||||
constexpr basic_symbol_text(const basic_fixed_string<StandardCharT, N>& std,
|
||||
const basic_fixed_string<char, M>& a) noexcept :
|
||||
standard_(std), ascii_(a)
|
||||
const basic_fixed_string<char, M>& ascii) noexcept :
|
||||
standard_(std), ascii_(ascii)
|
||||
{
|
||||
detail::validate_ascii_string<M>(a.data_);
|
||||
detail::validate_ascii_string<M>(ascii.data_);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto& standard() { return standard_; }
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <units/bits/external/downcasting.h>
|
||||
|
||||
// IWYU pragma: begin_exports
|
||||
#include <units/bits/derived_unit.h>
|
||||
#include <units/bits/derived_scaled_unit.h>
|
||||
#include <units/bits/external/fixed_string.h>
|
||||
#include <units/magnitude.h>
|
||||
#include <units/prefix.h>
|
||||
@@ -36,6 +36,13 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename>
|
||||
inline constexpr bool can_be_prefixed = false;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief A common point for a hierarchy of units
|
||||
*
|
||||
@@ -63,58 +70,34 @@ using downcast_unit = downcast<scaled_unit<M, typename dimension_unit<D>::refere
|
||||
template<Unit U1, Unit U2>
|
||||
struct same_unit_reference : is_same<typename U1::reference, typename U2::reference> {};
|
||||
|
||||
/**
|
||||
* @brief An unnamed unit
|
||||
*
|
||||
* Defines a new unnamed (in most cases coherent) derived unit of a specific derived dimension
|
||||
* and it should be passed in this dimension's definition.
|
||||
*
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
*/
|
||||
template<typename Child>
|
||||
struct unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {
|
||||
static constexpr bool is_named = false;
|
||||
using prefix_family = no_prefix;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A named unit
|
||||
*
|
||||
* Defines a named (in most cases coherent) unit that is then passed to a dimension definition.
|
||||
* A named unit may be used by other units defined with the prefix of the same type, unless
|
||||
* no_prefix is provided for PF template parameter (in such a case it is impossible to define
|
||||
* a prefix unit based on this one).
|
||||
* A named unit may be composed with a prefix to create a prefixed_unit.
|
||||
*
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
* @tparam Symbol a short text representation of the unit
|
||||
* @tparam PF no_prefix or a type of prefix family
|
||||
*/
|
||||
template<typename Child, basic_symbol_text Symbol, PrefixFamily PF>
|
||||
template<typename Child, basic_symbol_text Symbol>
|
||||
struct named_unit : downcast_dispatch<Child, scaled_unit<as_magnitude<1>(), Child>> {
|
||||
static constexpr bool is_named = true;
|
||||
static constexpr auto symbol = Symbol;
|
||||
using prefix_family = PF;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A scaled unit
|
||||
* @brief A named scaled unit
|
||||
*
|
||||
* Defines a new named unit that is a scaled version of another unit. Such unit can be used by
|
||||
* other units defined with the prefix of the same type, unless no_prefix is provided for PF
|
||||
* template parameter (in such a case it is impossible to define a prefix unit based on this
|
||||
* one).
|
||||
* Defines a new named unit that is a scaled version of another unit.
|
||||
* A named unit may be composed with a prefix to create a prefixed_unit.
|
||||
*
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
* @tparam Symbol a short text representation of the unit
|
||||
* @tparam PF no_prefix or a type of prefix family
|
||||
* @tparam M the Magnitude by which to scale U
|
||||
* @tparam U a reference unit to scale
|
||||
*/
|
||||
template<typename Child, basic_symbol_text Symbol, PrefixFamily PF, Magnitude auto M, Unit U>
|
||||
template<typename Child, basic_symbol_text Symbol, Magnitude auto M, Unit U>
|
||||
struct named_scaled_unit : downcast_dispatch<Child, scaled_unit<M * U::mag, typename U::reference>> {
|
||||
static constexpr bool is_named = true;
|
||||
static constexpr auto symbol = Symbol;
|
||||
using prefix_family = PF;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -128,14 +111,23 @@ struct named_scaled_unit : downcast_dispatch<Child, scaled_unit<M * U::mag, type
|
||||
* @tparam P prefix to be appied to the reference unit
|
||||
* @tparam U reference unit
|
||||
*/
|
||||
template<typename Child, Prefix P, Unit U>
|
||||
requires U::is_named && std::same_as<typename P::prefix_family, typename U::prefix_family>
|
||||
template<typename Child, Prefix P, NamedUnit U>
|
||||
requires detail::can_be_prefixed<U>
|
||||
struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typename U::reference>> {
|
||||
static constexpr bool is_named = true;
|
||||
static constexpr auto symbol = P::symbol + U::symbol;
|
||||
using prefix_family = no_prefix;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A coherent unit of a derived quantity
|
||||
*
|
||||
* Defines a new coherent unit of a derived quantity. It should be passed as a coherent unit
|
||||
* in the dimension's definition for such a quantity.
|
||||
*
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
*/
|
||||
template<typename Child>
|
||||
struct derived_unit : downcast_dispatch<Child, scaled_unit<ratio(1), Child>> {};
|
||||
|
||||
/**
|
||||
* @brief A unit with a deduced ratio and symbol
|
||||
*
|
||||
@@ -149,36 +141,10 @@ struct prefixed_unit : downcast_dispatch<Child, scaled_unit<P::mag * U::mag, typ
|
||||
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe
|
||||
* @tparam URest the units for the rest of dimensions from the recipe
|
||||
*/
|
||||
template<typename Child, DerivedDimension Dim, Unit U, Unit... URest>
|
||||
requires detail::same_scaled_units<typename Dim::recipe, U, URest...> &&
|
||||
(U::is_named && (URest::is_named && ... && true))
|
||||
struct derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
|
||||
static constexpr bool is_named = false;
|
||||
static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
|
||||
using prefix_family = no_prefix;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A named unit with a deduced ratio
|
||||
*
|
||||
* Defines a new unit with a deduced ratio and the given symbol based on the recipe from the provided
|
||||
* derived dimension. The number and order of provided units should match the recipe of the
|
||||
* derived dimension. All of the units provided should also be a named ones so it is possible
|
||||
* to create a deduced symbol text.
|
||||
*
|
||||
* @tparam Child inherited class type used by the downcasting facility (CRTP Idiom)
|
||||
* @tparam Dim a derived dimension recipe to use for deduction
|
||||
* @tparam Symbol a short text representation of the unit
|
||||
* @tparam PF no_prefix or a type of prefix family
|
||||
* @tparam U the unit of the first composite dimension from provided derived dimension's recipe
|
||||
* @tparam URest the units for the rest of dimensions from the recipe
|
||||
*/
|
||||
template<typename Child, DerivedDimension Dim, basic_symbol_text Symbol, PrefixFamily PF, Unit U, Unit... URest>
|
||||
template<typename Child, DerivedDimension Dim, NamedUnit U, NamedUnit... URest>
|
||||
requires detail::same_scaled_units<typename Dim::recipe, U, URest...>
|
||||
struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U, URest...>> {
|
||||
static constexpr bool is_named = true;
|
||||
static constexpr auto symbol = Symbol;
|
||||
using prefix_family = PF;
|
||||
struct derived_scaled_unit : downcast_dispatch<Child, detail::derived_scaled_unit<Dim, U, URest...>> {
|
||||
static constexpr auto symbol = detail::derived_symbol_text<Dim, U, URest...>();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -186,19 +152,14 @@ struct named_derived_unit : downcast_dispatch<Child, detail::derived_unit<Dim, U
|
||||
*
|
||||
* Defines a named alias for another unit. It is useful to assign alternative names and symbols
|
||||
* to the already predefined units (i.e. "tonne" for "megagram").
|
||||
* An alias unit may be used by other units defined with the prefix of the same type, unless
|
||||
* no_prefix is provided for PF template parameter (in such a case it is impossible to define
|
||||
* a prefix unit based on this one).
|
||||
* A alias unit may be composed with a prefix to create a prefixed_alias_unit.
|
||||
*
|
||||
* @tparam U Unit for which an alias is defined
|
||||
* @tparam Symbol a short text representation of the unit
|
||||
* @tparam PF no_prefix or a type of prefix family
|
||||
*/
|
||||
template<Unit U, basic_symbol_text Symbol, PrefixFamily PF>
|
||||
template<Unit U, basic_symbol_text Symbol>
|
||||
struct alias_unit : U {
|
||||
static constexpr bool is_named = true;
|
||||
static constexpr auto symbol = Symbol;
|
||||
using prefix_family = PF;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -215,20 +176,55 @@ struct alias_unit : U {
|
||||
// TODO gcc bug: 95015
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95015
|
||||
// template<Unit U, Prefix P, AliasUnit AU>
|
||||
// requires (!AliasUnit<U>) && std::same_as<typename P::prefix_family, typename AU::prefix_family>
|
||||
template<Unit U, Prefix P, Unit AU>
|
||||
requires AU::is_named && std::same_as<typename P::prefix_family, typename AU::prefix_family>
|
||||
// requires (!AliasUnit<U>)
|
||||
template<Unit U, Prefix P, NamedUnit AU>
|
||||
requires detail::can_be_prefixed<AU>
|
||||
struct prefixed_alias_unit : U {
|
||||
static constexpr bool is_named = true;
|
||||
static constexpr auto symbol = P::symbol + AU::symbol;
|
||||
using prefix_family = no_prefix;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Unknown unit
|
||||
* @brief Unknown coherent unit
|
||||
*
|
||||
* Used as a coherent unit of an unknown dimension.
|
||||
*/
|
||||
struct unknown_coherent_unit : unit<unknown_coherent_unit> {};
|
||||
struct unknown_coherent_unit : derived_unit<unknown_coherent_unit> {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Child, basic_symbol_text Symbol>
|
||||
void is_named_impl(const volatile named_unit<Child, Symbol>*);
|
||||
|
||||
template<typename Child, basic_symbol_text Symbol, ratio R, typename U>
|
||||
void is_named_impl(const volatile named_scaled_unit<Child, Symbol, R, U>*);
|
||||
|
||||
template<typename Child, typename P, typename U>
|
||||
void is_named_impl(const volatile prefixed_unit<Child, P, U>*);
|
||||
|
||||
template<typename U, basic_symbol_text Symbol>
|
||||
void is_named_impl(const volatile alias_unit<U, Symbol>*);
|
||||
|
||||
template<typename U, typename P, typename AU>
|
||||
void is_named_impl(const volatile prefixed_alias_unit<U, P, AU>*);
|
||||
|
||||
template<Unit U>
|
||||
inline constexpr bool is_named<U> = requires(U * u) { is_named_impl(u); };
|
||||
|
||||
template<typename Child, basic_symbol_text Symbol>
|
||||
void can_be_prefixed_impl(const volatile named_unit<Child, Symbol>*);
|
||||
|
||||
template<typename Child, basic_symbol_text Symbol, ratio R, typename U>
|
||||
void can_be_prefixed_impl(const volatile named_scaled_unit<Child, Symbol, R, U>*);
|
||||
|
||||
template<typename U, basic_symbol_text Symbol>
|
||||
void can_be_prefixed_impl(const volatile alias_unit<U, Symbol>*);
|
||||
|
||||
template<Unit U>
|
||||
inline constexpr bool can_be_prefixed<U> = requires(U * u) { can_be_prefixed_impl(u); };
|
||||
|
||||
template<ratio R, typename U>
|
||||
inline constexpr bool can_be_prefixed<scaled_unit<R, U>> = can_be_prefixed<typename U::reference>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace units
|
||||
|
||||
Reference in New Issue
Block a user