Skip to content

Commit

Permalink
Deployed 87bf5b3 to main with MkDocs 1.5.3 and mike 1.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Apr 25, 2024
1 parent 3662005 commit 704ce15
Show file tree
Hide file tree
Showing 6 changed files with 1,376 additions and 856 deletions.
140 changes: 135 additions & 5 deletions main/au.hh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <type_traits>
#include <utility>

// Version identifier: 0.3.4-5-gffea274
// Version identifier: 0.3.4-6-g87bf5b3
// <iostream> support: INCLUDED
// List of included units:
// amperes
Expand Down Expand Up @@ -651,6 +651,136 @@ struct identity {
} // namespace stdx
} // namespace au



namespace au {

//
// A type trait that determines if a type is a valid representation type for `Quantity` or
// `QuantityPoint`.
//
template <typename T>
struct IsValidRep;

//
// A type trait to indicate whether the product of two types is a valid rep.
//
// Will validly return `false` if the product does not exist.
//
template <typename T, typename U>
struct IsProductValidRep;

//
// A type trait to indicate whether the quotient of two types is a valid rep.
//
// Will validly return `false` if the quotient does not exist.
//
template <typename T, typename U>
struct IsQuotientValidRep;

////////////////////////////////////////////////////////////////////////////////////////////////////
// Implementation details below.
////////////////////////////////////////////////////////////////////////////////////////////////////

// Forward declarations for main Au container types.
template <typename U, typename R>
class Quantity;
template <typename U, typename R>
class QuantityPoint;
template <typename T>
struct CorrespondingQuantity;

namespace detail {
template <typename T>
struct IsAuType : std::false_type {};

template <typename U, typename R>
struct IsAuType<::au::Quantity<U, R>> : std::true_type {};

template <typename U, typename R>
struct IsAuType<::au::QuantityPoint<U, R>> : std::true_type {};

template <typename T>
using CorrespondingUnit = typename CorrespondingQuantity<T>::Unit;

template <typename T>
using CorrespondingRep = typename CorrespondingQuantity<T>::Rep;

template <typename T>
struct HasCorrespondingQuantity
: stdx::conjunction<stdx::experimental::is_detected<CorrespondingUnit, T>,
stdx::experimental::is_detected<CorrespondingRep, T>> {};

template <typename T>
using LooksLikeAuOrOtherQuantity = stdx::disjunction<IsAuType<T>, HasCorrespondingQuantity<T>>;

// We need a way to form an "operation on non-quantity types only". That is: it's some operation,
// but _if either input is a quantity_, then we _don't even form the type_.
//
// The reason this very specific machinery lives in `rep.hh` is because when we're dealing with
// operations on "types that might be a rep", we know we can exclude quantity types right away.
// (Note that we're using the term "quantity" in an expansive sense, which includes not just
// `au::Quantity`, but also `au::QuantityPoint`, and "quantity-like" types from other libraries
// (which we consider as "anything that has a `CorrespondingQuantity`".
template <template <class...> class Op, typename... Ts>
struct ResultIfNoneAreQuantity;
template <template <class...> class Op, typename... Ts>
using ResultIfNoneAreQuantityT = typename ResultIfNoneAreQuantity<Op, Ts...>::type;

// Default implementation where we know that none are quantities.
template <bool AreAnyQuantity, template <class...> class Op, typename... Ts>
struct ResultIfNoneAreQuantityImpl : stdx::type_identity<Op<Ts...>> {};

// Implementation if any of the types are quantities.
template <template <class...> class Op, typename... Ts>
struct ResultIfNoneAreQuantityImpl<true, Op, Ts...> : stdx::type_identity<void> {};

// The main implementation.
template <template <class...> class Op, typename... Ts>
struct ResultIfNoneAreQuantity
: ResultIfNoneAreQuantityImpl<stdx::disjunction<LooksLikeAuOrOtherQuantity<Ts>...>::value,
Op,
Ts...> {};

// The `std::is_empty` is a good way to catch all of the various unit and other monovalue types in
// our library, which have little else in common. It's also just intrinsically true that it
// wouldn't make much sense to use an empty type as a rep.
template <typename T>
struct IsKnownInvalidRep
: stdx::disjunction<std::is_empty<T>, LooksLikeAuOrOtherQuantity<T>, std::is_same<void, T>> {};

// The type of the product of two types.
template <typename T, typename U>
using ProductType = decltype(std::declval<T>() * std::declval<U>());

template <typename T, typename U>
using ProductTypeOrVoid = stdx::experimental::detected_or_t<void, ProductType, T, U>;

// The type of the quotient of two types.
template <typename T, typename U>
using QuotientType = decltype(std::declval<T>() / std::declval<U>());

template <typename T, typename U>
using QuotientTypeOrVoid = stdx::experimental::detected_or_t<void, QuotientType, T, U>;
} // namespace detail

// Implementation for `IsValidRep`.
//
// For now, we'll accept anything that isn't explicitly known to be invalid. We may tighten this up
// later, but this seems like a reasonable starting point.
template <typename T>
struct IsValidRep : stdx::negation<detail::IsKnownInvalidRep<T>> {};

template <typename T, typename U>
struct IsProductValidRep
: IsValidRep<detail::ResultIfNoneAreQuantityT<detail::ProductTypeOrVoid, T, U>> {};

template <typename T, typename U>
struct IsQuotientValidRep
: IsValidRep<detail::ResultIfNoneAreQuantityT<detail::QuotientTypeOrVoid, T, U>> {};

} // namespace au

// This file provides drop-in replacements for certain standard library function objects for
// comparison and arithmetic: `std::less<void>`, `std::plus<void>`, etc.
//
Expand Down Expand Up @@ -3711,21 +3841,21 @@ class Quantity {
}

// Scalar multiplication.
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
template <typename T, typename = std::enable_if_t<IsProductValidRep<RepT, T>::value>>
friend constexpr auto operator*(Quantity a, T s) {
return make_quantity<UnitT>(a.value_ * s);
}
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
template <typename T, typename = std::enable_if_t<IsProductValidRep<T, RepT>::value>>
friend constexpr auto operator*(T s, Quantity a) {
return make_quantity<UnitT>(s * a.value_);
}

// Scalar division.
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
template <typename T, typename = std::enable_if_t<IsQuotientValidRep<RepT, T>::value>>
friend constexpr auto operator/(Quantity a, T s) {
return make_quantity<UnitT>(a.value_ / s);
}
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
template <typename T, typename = std::enable_if_t<IsQuotientValidRep<T, RepT>::value>>
friend constexpr auto operator/(T s, Quantity a) {
warn_if_integer_division<T>();
return make_quantity<decltype(pow<-1>(unit))>(s / a.value_);
Expand Down
Loading

0 comments on commit 704ce15

Please sign in to comment.