3

I'm trying to create a universal conversion function which aims to convert base-any numeral system to decimal:

namespace detail
{
    template<char Chs> constexpr auto
    toDecImpl()
    {
        return Chs > '9' ? Chs - 'A' + 10 : Chs - '0';
    }
} // namespace detail
template<int from, char... Chs> constexpr auto
toDec()
{
    int ret{};

    return ((ret *= from, ret += detail::toDecImpl<Chs>()), ...);
}

And the use case is like:

inline namespace literals
{
    template<char... Chs> constexpr auto
    operator"" _B()
    {
        return toDec<2, Chs...>();
    }
    template<char... Chs> constexpr auto
    operator"" _O()
    {
        return toDec<8, Chs...>();
    }
    template<char... Chs> constexpr auto
    operator"" _H()
    {
        return toDec<16, Chs...>();
    }
}

As for heximal, which contains non-digit char likeA~F: int a = 82ABC_H, and it will give an error like: invalid digit A in decimal constant

live demo

Of course, I can use operator ""_H(const char*, std::size_t) for base- >10 number system, but it cannot re-use my toDecImpl unless I write another one for these number systems.

Question: Is there any elegant workaround here to re-use toDecImpl for number system that contain alpha like hex?

Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • 2
    `'A' + 10` ain't portable I'm afraid. – Bathsheba May 09 '19 at 07:09
  • 1
    @Bathsheba That's like saying "signed integers are not necessarily 2s-compliment". Luckily, the committee changed that in C++20. Find a machine that you want to run this code on that doesn't support ASCII or Unicode. – Indiana Kernick May 09 '19 at 07:27
  • @Kerndog73 Consider language lawyers. – L. F. May 09 '19 at 07:37
  • 1
    @Kerndog73: Plenty in investment banks for example. Just make the thing portable, pretty please with sugar on top. It's not that difficult cf. all the template magic. – Bathsheba May 09 '19 at 07:37

1 Answers1

0

If I understood your definition of "elegant" correctly, no, this is not possible. A user-defined literal cannot alter the syntax. Per [lex.icon], you can either use 0x or 0X with hexadecimal digits, or you can only use decimal digits without 0x or 0X. The compiler checks this before feeding the actual content to the UDL function.

Yeah, of course you can use string literals. That should be an acceptable workaround in this case.

L. F.
  • 19,445
  • 8
  • 48
  • 82