Станет ли std :: string нашей строкой времени компиляции?

Многие разработчики и авторы библиотек уже несколько лет борются со строками времени компиляции - поскольку стандартная (библиотечная) строка, std::string, требует динамического выделения памяти и не является constexpr.

Итак, у нас есть куча вопросов и сообщений в блоге о том, как правильно составить строки во время компиляции:

Теперь мы узнали, что new не только доступен в коде constexpr, позволяющего динамическое выделение во время компиляции, но, фактически, std::string станет constexpr в C++ 20 (C++ стандартный отчет совещания рабочей группы Херба Саттера).

Означает ли это, что для кода C++ 20 и выше мы должны бросить все эти изящные реализации строк времени компиляции и просто всегда идти с std::string?

Если нет - когда мы это сделаем и когда мы будем придерживаться того, что возможно сегодня (кроме, конечно, обратно-совместимого кода)?


Примечание: я не говорю о строках, содержимое которых является частью их типа, то есть не говорю об эквиваленте std::integral_constant; это определенно не будет std::string.

Ответ 1

Это зависит от того, что вы подразумеваете под "строкой constexpr".

С++ 20 позволяет вам использовать std::string внутри функции, помеченной constexpr (или consteval). Такая функция может создавать string, манипулировать ею и т.д., Как и любой литеральный тип. Однако эта строка не может constexpr код non- constexpr; это было бы non- переходным распределением и запрещено.

Дело в том, что все примеры, которые вы приводите, являются попытками использовать строки в качестве параметров шаблона. Это похожая, но все же другая вещь. Вы не просто говорите о построении строки во время компиляции; Теперь вы хотите использовать его для создания шаблона.

С++ 20 решает эту проблему, позволяя пользовательским типам быть параметрами шаблона. Но требования к таким типам гораздо более строгие, чем просто буквальные типы. Тип должен, по существу, быть проверяемым на равенство посредством побайтного сравнения. И даже constexpr -capable std::string может этого сделать.

Но std::array<char, N> может это сделать. И если вы находитесь в коде constexpr, вызовите функцию constexpr которая возвращает std::string, и сохраните эту строку в значении constexpr, тогда string::size() будет функцией constexpr. Таким образом, вы можете использовать это, чтобы заполнить N для вашего массива.

Копирование символов в constexpr array (так как это значение constexpr, оно неизменяемое) немного сложнее, но выполнимо.

Таким образом, С++ 20 решает эту проблему, но не (напрямую) с помощью std::string.