Boost logo

Boost :

Subject: Re: [boost] [config/multiprecision/units/general] Do we have a policy for user-defined-literals?
From: Peter Sommerlad (peter.sommerlad_at_[hidden])
Date: 2013-05-06 06:06:55


Hi,

Vicente made me aware of that post. Since I am guilty, I'd like to answer.

First of all, John Maddock is right in almost everything... my fault.

However, let me defend what's there and confess what shouldn't be there.

As John wrote:
> I've been experimenting with the new C++11 feature "user-defined-literals", and they're pretty impressive ;-)

that's how I started as well....

1. using the parsing version for chrono literals is bullshit, John is right. The standard proposal I submitted does only define the regular numeric literal operators: operator"" h(unsigned long long) and operator"" h(long double), etc.

2. one can use the template version of operator"" for two things:
* parsing integer values in non-standard bases, i.e., ternary
* determining the best fitting type for integral values like the compiler does for integers, this can not be done through the cooked version, because it requires a template parameter for the meta function.
2.a the latter is a reason where it can make sense for a concrete chrono implementation to use the parsing version for the suffixes, since it depends on the implementation which integral range is useful/used for representing the duration (at least in the standard version), where it is open which integral type is used for the representation (i.e. at least 23 bits for hours). But that is really only interesting when you actually use that many hours.

3. the parsing can be "simplified" with using a more complex expression like John proposes, instead of the monstrous template dispatching I implemented. I haven't tested which is faster for which compiler yet and unfortunately doesn't have the time to do so soon. John's version is definitely shorter than the many overloads but requires an additional template parameter, so it is not a direct replacement to my coded version. However, this way it avoids the pow multiplications.

(see also inline below).

So thank you for teaching me something.

Regards
Peter.

On 28.04.2013, at 10:12, John Maddock <john_at_[hidden]> wrote:

>> 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.
The latter will be standardized to be 0b101010 in C++14. So not many useful things remain, unless you want ternary literals :-)

> What's the rationale for the chrono integer literals parsing the ints themselves rather than using cooked literals?
none. It was a ridiculous experiment by me and I forgot to adapt it back again to the cooked version.
>
> Cheers, John.
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-- 
Prof. Peter Sommerlad
Institut für Software: Bessere Software - Einfach, Schneller!
HSR Hochschule für Technik Rapperswil
Oberseestr 10, Postfach 1475, CH-8640 Rapperswil
http://ifs.hsr.ch http://cute-test.com http://linticator.com http://includator.com
tel:+41 55 222 49 84 == mobile:+41 79 432 23 32
fax:+41 55 222 46 29 == mailto:peter.sommerlad_at_[hidden]

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk