@@ -236,13 +236,29 @@ struct unit_interface {
236236 return kind_of<detail::get_associated_quantity (U{})>;
237237 }
238238
239- template <std::intmax_t Num, std::intmax_t Den = 1 , Unit U>
239+ // Clang <= 18 does not support default template arguments in friend function templates.
240+ // The two overloads below are a workaround. The intended library API (and the one that
241+ // should be proposed for ISO standardization) is a single function template:
242+ //
243+ // template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
244+ // requires(Den != 0)
245+ // [[nodiscard]] friend consteval Unit auto pow(U u)
246+ // {
247+ // return detail::expr_pow<Num, Den, derived_unit, struct one>(u);
248+ // }
249+ template <std::intmax_t Num, std::intmax_t Den, Unit U>
240250 requires (Den != 0 )
241251 [[nodiscard]] friend consteval Unit auto pow (U u)
242252 {
243253 return detail::expr_pow<Num, Den, derived_unit, struct one >(u);
244254 }
245255
256+ template <std::intmax_t Num, Unit U>
257+ [[nodiscard]] friend consteval Unit auto pow (U u)
258+ {
259+ return detail::expr_pow<Num, 1 , derived_unit, struct one >(u);
260+ }
261+
246262 [[nodiscard]] friend consteval Unit auto sqrt (Unit auto u) { return pow<1 , 2 >(u); }
247263 [[nodiscard]] friend consteval Unit auto cbrt (Unit auto u) { return pow<1 , 3 >(u); }
248264 [[nodiscard]] friend consteval Unit auto square (Unit auto u) { return pow<2 >(u); }
@@ -359,14 +375,14 @@ struct named_unit<Symbol, QS, PO> : detail::unit_interface {
359375 * @tparam Unit a unit for which we provide a special name
360376 */
361377template <symbol_text Symbol, Unit auto U>
362- requires (!Symbol.empty())
378+ requires (!Symbol.empty()) && detail::magnitude_is_positive<mp_units::get_canonical_unit(U).mag>
363379struct named_unit<Symbol, U> : decltype(U)::_base_type_ {
364380 using _base_type_ = named_unit; // exposition only
365381 static constexpr auto _symbol_ = Symbol; // /< Unique unit identifier
366382};
367383
368384template <symbol_text Symbol, Unit auto U, PointOrigin auto PO>
369- requires (!Symbol.empty())
385+ requires (!Symbol.empty()) && detail::magnitude_is_positive<mp_units::get_canonical_unit(U).mag>
370386struct named_unit<Symbol, U, PO> : decltype(U)::_base_type_ {
371387 using _base_type_ = named_unit; // exposition only
372388 static constexpr auto _symbol_ = Symbol; // /< Unique unit identifier
@@ -383,15 +399,17 @@ struct named_unit<Symbol, U, PO> : decltype(U)::_base_type_ {
383399 * @tparam QuantitySpec a specification of a quantity to be measured with this unit
384400 */
385401template <symbol_text Symbol, Unit auto U, detail::QuantityKindSpec auto QS>
386- requires (!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
402+ requires (!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension) &&
403+ detail::magnitude_is_positive<mp_units::get_canonical_unit(U).mag>
387404struct named_unit<Symbol, U, QS> : decltype(U)::_base_type_ {
388405 using _base_type_ = named_unit; // exposition only
389406 static constexpr auto _symbol_ = Symbol; // /< Unique unit identifier
390407 static constexpr auto _quantity_spec_ = QS;
391408};
392409
393410template <symbol_text Symbol, Unit auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
394- requires (!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
411+ requires (!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension) &&
412+ detail::magnitude_is_positive<mp_units::get_canonical_unit(U).mag>
395413struct named_unit<Symbol, U, QS, PO> : decltype(U)::_base_type_ {
396414 using _base_type_ = named_unit; // exposition only
397415 static constexpr auto _symbol_ = Symbol; // /< Unique unit identifier
0 commit comments