 # STD-PROPOSALS

Subject: [std-proposals] Physical Units / Composite UDL / Named postfix
From: Cleiton Santoia (cleitonsantoia_at_[hidden])
Date: 2020-06-03 20:55:39

I was looking at p1935r2.html
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1935r2.html> and
decided to give my 2 cents : "composite" UDLs.

One of the dreams of every "Units" library is to be able define
k,c,m... "multiple"
UDLs ( defined probably in <ratio> ) and combine them with A, m and L
"unity"
(probably defined in some future <unity> header) UDLs, respecting the
position
where "multiples" and "unities" appears.

Allowing "most vexing phrase" and any classes as parameters to UDL, it
might be
possible.

1 - Composite UDL ( The blue code is new syntax )

Consider:

template<typename T, typename Ratio_T>
struct quantity : Ratio_T {
T quant;
constexpr quantity (T v) : quant(v) {}
};

constexpr quantity<long double, std::kilo> operator"" k ( long double v )
{
return {v};
}

struct unity {};

template<typename T, typename Ratio_T>
struct len : quantity<T, Ratio_T>, unity {
using quantity<T, Ratio_T>::quantity;
};

auto pi_km = 3.1415k; // 3.1415 kilos without unity works fine in c++17

template<typename T, typename Ratio_T>
constexpr length<T, Ratio_T> operator"" m ( const quantity<T, Ratio_T>& q )
{
return {q};
}

auto l = 3.1415km; // 3.1415 kilometers
// since udl "km" cannot be found, try 3.1415k
// if it exists, (it does) evaluates to quantity<...>
// now, try to find UDL "m" that works with
quantity<...>
// if it exists, (it does) evaluates to len<...>.

Ok IÂ´m aware that 'most vexing' + 'overload on classes' might become a
parsing nightmare.

2 - Another possible design is "postfix named operator" ( could work even
on runtime )
Consider previous class quantity, plus a postfix member "A" for amperes

template<typename T, typename Ratio_T>
struct quantity : Ratio_T {
T quant;
constexpr quantity (T v) : quant(v) {}

// postfix syntax, like postfix ++
constexpr length<T, Ratio_T> operator A(int) {
return {quant};
}
};

auto x = 10.0kA; // x = 10 kilo Ampers, ( most vexing finds 10.0m, then
finds postfix "A" in quantity<...>
auto y = 11.0k; // y = 11 kilo ( just quantity<...> ), without any unity
auto z = y A; // z = 11 kilo Ampers, ( need a space between y and A );

3 - Ambiguity ( Little case of "m" that may be milli or meter )

template<typename T>
struct ambiguous_m {
T quant;
};
constexpr ambiguous_m<long double> operator"" m ( long double v )
{
return {v};
};

template<typename T>
constexpr length<T, std::mili> operator"" m ( const ambiguous_m<T>& v )
{
return {v};
}

const auto s = 1s; // chrono 1 second;

template<typename T, typename Rep, typename Period>
constexpr speed< length<T, std::mili>, std::chrono::duration<Rep, Period> >
operator /( const ambiguous_m<T>& x, std::chrono::duration<Rep, Period>
dur ) {
return {x, dur};
}

auto x = 10.0mm; // ok ambiguous_m sufixxed by another m -> millimeter;
auto z = 20.0m/s; // ok ambiguous_m "divided" by chrono::duration ->
speed;

or define m as meter since the beginning, instead of ambiguous_m, IÂ´m open
to opinions.

4 - Unicode identifiers

auto x = 10.0ÂµA; // micro Ampere
// "sÂ²" might be a constant of type square seconds
seconds
// y is of type "angular acceleration"

auto z = 3mÂ³; // "mÂ³" is a udl: constexpr meter operator""
mÂ³(unsigned long long int) ...

auto e = 12.0NÂ·m; // "N" is an UDL that converts 12.0 in "struct newton"
// "Â·" is a postfix operator in "newton" to newton
itself
// "m" is a postfix operator in "newton" to
"newton-meter"

I still have some concerns upon the praticallity, and how this whould be
typed in keyboards around the world, in my keyboard I do have easy Â¹ Â² Â³
and Â°, but not Â·, nor Âµ.
Nontheless, 10.0ÂµA is a beautiful code.

BR
Cleiton

Standard Proposals Archives on Google Groups