I was looking at 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
auto y = 1.7rad/s²;  // rad is an UDL that converts 1.7 in radian type
                     // "s²" might be a constant of type square seconds
                     // "/" is an overloaded operator on radians and square 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