Можно ли создать пользовательский литерал, который преобразует строковые литералы в массив собственного типа? - PullRequest
0 голосов
/ 09 сентября 2018

Можно ли создать пользовательский литерал, который преобразует строковые литералы в массив собственного типа?

Предположим, у меня есть собственный тип байта, mylib::byte:

namespace mylib {
    enum class byte: unsigned char { };
}

Так, например, "Hello"_X должен иметь тип mylib::byte[5] со значением { 'H', 'e', 'l', 'l', 'o' }.


Вот фон, так что, возможно, вы можете порекомендовать другое решение.

У меня есть класс utf-8, который хранит mylib::byte * и длину (это работает как std::string_view, ему не принадлежит область памяти):

namespace mylib {
    class utf8 {
        const byte *m_string;
        int m_length;
    };
}

Я хотел бы иметь возможность сконструировать mylib::utf8 со строковыми литералами в коде удобно, что-то вроде этого:

mylib::utf8 u = "Hello";

В настоящее время я использую reinterpret_cast, то есть UB:

namespace mylib {
    class utf8 {
        const byte *m_string;
        int m_length;

    public:
        utf8(const byte *s) {
            m_string = s;
            m_length = ...;
        }
        utf8(const char *s) {
            m_string = reinterpret_cast<const byte *>(s); // causes UB afterwards
            m_length = ...;
        }
    };
}

Поэтому я подумал, что хотел бы иметь что-то подобное, чтобы избежать UB:

mylib::utf8 u = "Hello"_X; // I'd like to have the constructor with `const byte *` to be called here

Примечание: использование mylib::byte обязательно, я не могу его изменить.

1 Ответ

0 голосов
/ 10 сентября 2018
mylib::utf8 operator "" _X(const char* c, std::size_t n) {
  auto* r = new mylib::byte[n];
  std::transform(c, c+n, r, [](auto c){ return (mylib::byte)(unsigned char)(c););
  return {r,n};
}

это соответствует всем вашим критериям, как написано; Вы не требовали нулевой утечки.

...