Subject: Re: [boost] [config/multiprecision/units/general] Do we have a policy for user-defined-literals?
From: John Maddock (john_at_[hidden])
Date: 2013-04-28 04:12:43


>If http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3402.pdf is the
>final version accepted for C++14, the standard will use, e.g.
>
>namespace std {
>namespace suffixes {
>namespace chrono {
>
>One of the advantages is that we can add some utilities. I helped Peter
>Sommerlad to port his reference implementation to Boost (See
>https://github.com/PeterSommerlad/UDLSuffixBoost/tree/master/boost/suffixes).
>There are some interesting utilities that make easier implementing
>suffixes. I guess it would like to name his library Boost.Suffixes.
>This doesn't means that we can not choose your option.

I hadn't seen that before, thanks for the heads up.

If we have UDL utilities in boost then I agree they should have their own
top-level namespace in Boost, whether it makes sense to group all literals
in there is another matter. My gut feeling is that users will find
boost::mylib::literals or boost::mylib::suffixes easier, but I can see how
it would make sense for the std to go your way.

BTW, I believe your implementation of parse_int is unnessarily complex,
looks like that whole file can be reduced to just:

template <unsigned base, unsigned long long val, char... Digits>
struct parse_int
{
    // The default specialization is also the termination condition:
    // it gets invoked only when sizeof...Digits == 0.
    static_assert(base<=16u,"only support up to hexadecimal");
    static constexpr unsigned long long value{ val };
};

template <unsigned base, unsigned long long val, char c, char... Digits>
struct parse_int<base, val, c, Digits...>
{
    static constexpr unsigned long long char_value = (c >= '0' && c <= '9')
            ? c - '0'
            : (c >= 'a' && c <= 'f')
            ? c - 'a'
            : (c >= 'A' && c <= 'F')
            ? c - 'A'
            : 400u;
    static_assert(char_value < base, "Encountered a digit out of range");
    static constexpr unsigned long long value{ parse_int<base, val * base +
char_value, Digits...>::value };
};

Typical usage is:

template <char...PACK>
constexpr unsigned long long operator "" _b()
{
   return parse_int<2, 0, PACK...>::value;
}

constexpr unsigned bt = 1001_b;

static_assert(bt == 9, "");

More than that though: I can't help but feel that base 8, 10 and 16 parsing
is much better (faster) handled by the compiler, so parse_int could be
reduced to base-2 parsing only which would simplify it still further.
What's the rationale for the chrono integer literals parsing the ints
themselves rather than using cooked literals?

Cheers, John.