Как создать 128-битный целочисленный литерал

У меня есть целочисленный литерал в формате 0x75f17d6b3588f843b13dea7c9c324e51. Есть ли способ избежать синтаксической ошибки компилятора "Целочисленный литерал слишком велик, чтобы быть представленным в любом целочисленном типе"?

Потому что я знаю, что могу работать с такими типами (я использую uint128_t из библиотеки EOS, и если я его вручную вставляю, он работает).

Есть ли способ каким-либо образом разобрать эту строку непосредственно в одно и то же целое число во время выполнения?

Ответы

Ответ 1

128-битные целые литералы не соответствуют стандарту, поэтому до реализации, если он хочет их разрешить. Большинство не делают этого, поэтому вам нужно разбить его на два 64-битных компонента и использовать побитовые операторы для их объединения:

__uint128_t num = ((__uint128_t)0x75f17d6b3588f843 << 64) | 0xb13dea7c9c324e51;

Хороший компилятор должен выполнять операции во время компиляции.

Ответ 2

Вы можете написать необработанный литерал-оператор (своего рода пользовательский литерал, начиная с С++ 11) для 128-битного целого числа.

Оператор raw literal принимает один параметр const char* качестве параметра. Вы можете написать тело функции для синтаксического анализа строки.

Например:

// Use __uint128_t for demonstration.
constexpr __uint128_t operator""_uint128_t(const char* x)
{
    __uint128_t y = 0;
    for (int i = 2; x[i] != '\0'; ++i)
    {
        y *= 16ull;
        if ('0' <= x[i] && x[i] <= '9')
            y += x[i] - '0';
        else if ('A' <= x[i] && x[i] <= 'F')
            y += x[i] - 'A' + 10;
        else if ('a' <= x[i] && x[i] <= 'f')
            y += x[i] - 'a' + 10;
    }
    return y;
}

Очевидно, что эта реализация проблематична, потому что я слишком ленив, чтобы разработать полное решение, оно поддерживает только шестнадцатеричное, оно не проверяет префикс 0x и т.д. И для этого требуется С++ 14 расслабленная функция constexpr. Но это демонстрирует, что вы можете фактически разобрать эту строку непосредственно в одно и то же целое число.

Позвольте проверить это:

int main()
{
    auto abc = 0x1234567890ABCDEFfedcba0987654321_uint128_t;
    std::uint64_t higher = abc >> 64;
    std::uint64_t lower = abc;
    std::cout << std::hex << higher << ' ' << lower;
}

http://coliru.stacked-crooked.com/a/fec4fc0fd4ff1418