Возможность создавать строки и манипулировать ими во время компиляции в C++ имеет несколько полезных применений. Хотя в C++ можно создавать строки во время компиляции, этот процесс очень громоздкий, поскольку строку необходимо объявить как вариативную последовательность символов, например
Такие операции, как объединение строк, извлечение подстроки и многие другие, можно легко реализовать как операции над последовательностями символов.
Можно ли более удобно объявлять строки во время компиляции? Если нет, то есть ли в разработке предложение, которое позволило бы удобно объявлять строки во время компиляции?
Почему существующие подходы не работают
В идеале мы хотели бы иметь возможность объявлять строки времени компиляции следующим образом:
или, используя пользовательские литералы,
Код: Выделить всё
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
где decltype(str2) будет иметь конструктор constexpr. Можно реализовать более запутанную версию подхода 1, воспользовавшись тем, что вы можете сделать следующее:
Однако массив должен иметь внешнюю связь, поэтому, чтобы подход 1 работал, нам придется написать что-то вроде этого:
Код: Выделить всё
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string;
return 0;
}
Само собой разумеется, это очень неудобно. Подход 2 на самом деле невозможен. Если бы мы объявили (
) литеральный оператор, то как нам указать тип возвращаемого значения? Поскольку нам нужен оператор для возврата переменной последовательности символов, нам нужно будет использовать параметр const char*, чтобы указать тип возвращаемого значения:
Код: Выделить всё
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
Это приводит к ошибке компиляции, поскольку s не является constexpr. Попытка обойти эту проблему, выполнив следующие действия, не поможет.
Код: Выделить всё
template
constexpr sequence operator"" _s() { return {}; }
Стандарт предписывает, что эта конкретная форма литерального оператора зарезервирована для целочисленных типов и типов с плавающей запятой. Хотя 123_s будет работать, abc_s — нет. Что, если мы вообще откажемся от пользовательских литералов и просто воспользуемся обычной функцией constexpr?
Код: Выделить всё
template
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
Как и раньше, мы столкнулись с проблемой: массив, который теперь является параметром функции constexpr, сам больше не является типом constexpr .
Я считаю, что должна быть возможность определить макрос препроцессора C, который принимает строку и размер строки в качестве аргументов и возвращает последовательность, состоящую из символов в строку (с использованием BOOST_PP_FOR, строкового преобразования, индексов массива и т. п.). Однако у меня нет времени (или достаточно интереса) реализовать такой макрос =)
Подробнее здесь:
https://stackoverflow.com/questions/158 ... rings-in-c