создание пользовательского суффикса для конвертации текстовой строки
создаю массив с сырыми данными, который должен быть объявлен глобально. Пример рабочего кода:
#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?
Ответы (1 шт):
Автор решения: HolyBlackCat
→ Ссылка
Я так понял, конкретный синтаксис вызова не очень важен? Я бы сделал 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';
}