создание пользовательского суффикса для конвертации текстовой строки

Рейтинг: 0Ответов: 1Опубликовано: 07.03.2023

создаю массив с сырыми данными, который должен быть объявлен глобально. Пример рабочего кода:

#include <iostream>
constexpr const uint8_t raw[] = { 0x01, 0x02, 0x03 };
const uint16_t sizeraw = sizeof raw;
void Print(const uint8_t* prt, int size)
{
    printf("size: %d\r\n", size);
    for (int i = 0; i < size; i++)
        printf("0x%02X ", *prt++);
    printf("\r\n");
}

int main()
{
    Print(raw, sizeraw);
    return 0;
}

По некоторым причинам, такая запись значений не устраивает. Не могу сообразить как работать с пользовательскими суффиксами. хотелось бы придти к такой форме записи:

constexpr const uint8_t raw[] = "010203"_hexstr;

Но не как не могу разобраться в конструкциях происходящих в

constexpr ??? operator "" _hexstr(const char* str, const size_t size)

Или можно как-то проще решить этот вопрос через define или constexpr?

Ответы

▲ 2Принят

Я так понял, конкретный синтаксис вызова не очень важен? Я бы сделал hex_str("010F12"), так:

#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>

[[nodiscard]] consteval int hex_digit(char ch)
{
    if (ch >= '0' && ch <= '9')
        return ch - '0';
    if (ch >= 'a' && ch <= 'f')
        return ch - 'a' + 10;
    if (ch >= 'A' && ch <= 'F')
        return ch - 'A' + 10;
    throw "Invalid hex digit.";
}

template <std::size_t N> requires(N % 2 == 1)
[[nodiscard]] consteval std::array<std::uint8_t, N/2> hex_str(const char (&source)[N])
{
    if (source[N-1] != '\0')
        throw "Expected null terminator.";
    std::array<std::uint8_t, N/2> ret{};
    for (std::size_t i = 0; i < N/2; i++)
        ret[i] = hex_digit(source[i * 2]) * 16 + hex_digit(source[i * 2 + 1]);
    return ret;
}

int main()
{
    constexpr auto ret = hex_str("010F12");
    for (int x : ret)
        std::cout << x << '\n';
}

С пользовательским литералом можно так, хотя мне не особо нравится передавать длинные строки в шаблонные параметры:

#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>

[[nodiscard]] consteval int hex_digit(char ch)
{
    if (ch >= '0' && ch <= '9')
        return ch - '0';
    if (ch >= 'a' && ch <= 'f')
        return ch - 'a' + 10;
    if (ch >= 'A' && ch <= 'F')
        return ch - 'A' + 10;
    throw "Invalid hex digit.";
}

template <std::size_t N> requires(N % 2 == 1)
struct ConstString
{
    std::array<std::uint8_t, N/2> value{};

    consteval ConstString(const char (&source)[N])
    {
        if (source[N-1] != '\0')
            throw "Expected null terminator.";
        for (std::size_t i = 0; i < N/2; i++)
            value[i] = hex_digit(source[i * 2]) * 16 + hex_digit(source[i * 2 + 1]);
    }
};

template <ConstString S>
[[nodiscard]] consteval decltype(S.value) operator""_hex_str()
{
    return S.value;
}

int main()
{
    constexpr auto ret = "010F12"_hex_str;
    for (int x : ret)
        std::cout << x << '\n';
}