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

Быстрая настройка: я хочу передать строки в моей программе в виде указателя и размера. У меня есть класс String и пользовательский литерал для построения литеральных строк:

struct String { const char *ptr; size_t sz; };

inline constexpr String operator "" _string(const char *s, size_t sz) {
  return {s, sz};
}

int main() {
  auto s = "hello"_string;
  s.ptr[0]; //<-- is this access guaranteed to work?
}

Указывает ли стандарт, что аргумент, передаваемый моему пользовательскому литеральному оператору, имеет статическую длительность? т.е. приведенный выше код фактически эквивалентен написанию:

int main() {
  String s{"hello", 5};
}

или компилятору / компоновщику разрешено оставлять меня с висящим указателем, когда я использую пользовательский литерал?

(В разделе 2.13.8 N4527, похоже, ничего не сказано о предмете класса хранения аргумента для пользовательских строковых литеральных операторов. Любые указатели на соответствующие разделы стандарта будут приветствоваться.)

1 ответ

Решение

Из [lex.ext]:

Если L является определяемым пользователем строковым литералом, пусть str будет литералом без его ud-суффикса, и пусть len будет количеством единиц кода в str (т. Е. Его длиной, исключая завершающий нулевой символ). Буквальный L трактуется как вызов формы:

operator "" X (str , len )

Из [lex.string]:

Оценка строкового литерала приводит к получению строкового литерала со статической продолжительностью хранения, инициализированного из заданных символов, как указано выше.

Так:

"hello"_string;

эквивалентно:

operator "" _string("hello", 5)

Как "hello" является строковым литералом, имеет статическую длительность хранения, поэтому у вас не будет висящего указателя.

Другие вопросы по тегам