Какова продолжительность статического хранения и время существования параметра шаблона, не являющегося типом, и как его ⇐ C++
Какова продолжительность статического хранения и время существования параметра шаблона, не являющегося типом, и как его
В C++ Weekly — Ep 313 — Проблема constexpr, на решение которой мне потребовалось 5 лет! Джейсон Тернер демонстрирует несколько методов времени компиляции для создания std::string< /code> во время компиляции, а затем передать его в std::string_view для использования во время выполнения.
Основная проблема заключается в том, что std::string использует new, внутри которого должен использоваться созданный во время компиляции std::string. отдельное выражение, такое как new, должно иметь соответствующий delete в том же контексте константы/время компиляции (извините за приблизительную формулировку).< /п> Поскольку код довольно длинный, я поместил его в конце вопроса.
Для этого он сначала показывает, как данные из std::string можно скопировать в std::array, сохраняя их внутри . >consteval функции (на данный момент я не уверен, что этого нельзя достичь просто с помощью функции constexpr).
Чего я вообще не понимаю, так это того, как он "продлевает" время жизни std::array за пределы непосредственного вызова функций, используя параметр шаблона, не относящийся к типу (NTTP), примерно на уровне 19. минут.
Мое (вероятно, неправильное) понимание стандарта заключается в том, что NTTP связан с объектом параметра шаблона со статической длительностью хранения:
Выражение id, именующее нетиповой параметр шаблона типа класса T, обозначает статический объект продолжительности хранения типа const T, известный как объект параметра шаблона, который является эквивалентом аргумента шаблона ([temp.type] ) в соответствующий аргумент шаблона после его преобразования в тип параметра шаблона ([temp.arg.nontype]). Никакие два объекта параметров шаблона не являются эквивалентными аргументам шаблона.
Тем не менее, я попытался поиграться с гораздо более простым (и надуманным) примером:
шаблон consteval const auto& make_static() { возвращаемое значение; } интервал основной() { [[maybe_unused]] const auto& i = make_static(); // (1) [[maybe_unused]] static const auto& j = make_static(); // (2) [[maybe_unused]] static constexpr auto& k = make_static(); // (3) [[maybe_unused]] constinit static auto& l = make_static(); // (4) вернуть я; } В прямом эфире
Ни одна из многих попыток не увенчалась успехом, как это видно из предоставленной связанной демо-версии. Разные составители ставят мне разные диагнозы.
Обычным шаблоном является то, что make_static() не считается постоянным выражением и возвращает ссылку на временный объект (что, насколько я понимаю, лучше, чем Гол Джейсона Тернера).
Примечание: GCC 13.2 (27 июля 2023 г.) даже жалуется на разыменование nullptr, но магистральная версия кажется более совместимой с MSVC и Clang.
Что не так с моим примером и как в этом свете работает вариант использования Джейсона Тернера?
#include #include #include #include #include #include // Какой-то алгоритм для генерации необычного std::string, возможно, во время компиляции constexpr std::string make_string(std::string_view base, const std::size_t повторение) { std::string retval; for (std::size_t count = 0; count < повторение; ++count) { ретвал += база; } возврат ретвал; } // Используйте только во время компиляции: он должен быть достаточно большим, чтобы вместить // копия строковых данных в «постоянном оцениваемом контексте» // NB: Вероятно, это неправильная формулировка выше. структура oversized_array { //статический constexpr std::size_t VeryLargeSize = 10 * 1024 * 1024; // Джейсон //пример токаря статический constexpr std::size_t VeryLargeSize = 1000; // Значение Джейсона Тернера было слишком большим для MSVC в Compiler Explorer std::array data{}; std::size_t размер; // Фактически используемый размер VeryLargeSize max. }; // Копируем содержащуюся строку в массив "достаточно большой". // Это помощник для to_right_sized_array ниже constexpr auto to_oversized_array(const std::string &str) { результат oversized_array; std::copy(str.begin(), str.end(), result.data.begin()); result.size = str.size(); вернуть результат; } // Копируем содержащуюся строку в массив того же размера. // Вызываемый объект — это лямбда, обертывающая make_string. // НО ЗА КЛАНГ шаблон consteval auto to_right_sized_array( Callable callable) { // версия Джейсона Тёрнера // constexpr auto to_right_sized_array(Callable callable) { // Кажется, так и есть // достаточно constexpr auto oversized = to_oversized_array(callable()); std::array результат; std::copy(oversized.data.begin(), std::next(oversized.data.begin(), oversized.size), результат.begin()); вернуть результат; } // Просто возвращает ссылку на «Данные» NTTP. // СУТЬ МОЕГО ВОПРОСА ЗДЕСЬ шаблон consteval const auto &make_static() { вернуть данные; } // Обертывание преобразованной из массива строки в string_view шаблон consteval auto to_string_view (Callable callable) { // std::array, поскольку NTTP — это C++20? constexpr auto &static_data = make_static(); return std::string_view{static_data.begin(), static_data.size()}; } интервал основной() { constexpr auto make_data = []() { return make_string("Привет, мир времени компиляции,", 3); }; constexpr статический автоматический просмотр = to_string_view(make_data); std::cout
В C++ Weekly — Ep 313 — Проблема constexpr, на решение которой мне потребовалось 5 лет! Джейсон Тернер демонстрирует несколько методов времени компиляции для создания std::string< /code> во время компиляции, а затем передать его в std::string_view для использования во время выполнения.
Основная проблема заключается в том, что std::string использует new, внутри которого должен использоваться созданный во время компиляции std::string. отдельное выражение, такое как new, должно иметь соответствующий delete в том же контексте константы/время компиляции (извините за приблизительную формулировку).< /п> Поскольку код довольно длинный, я поместил его в конце вопроса.
Для этого он сначала показывает, как данные из std::string можно скопировать в std::array, сохраняя их внутри . >consteval функции (на данный момент я не уверен, что этого нельзя достичь просто с помощью функции constexpr).
Чего я вообще не понимаю, так это того, как он "продлевает" время жизни std::array за пределы непосредственного вызова функций, используя параметр шаблона, не относящийся к типу (NTTP), примерно на уровне 19. минут.
Мое (вероятно, неправильное) понимание стандарта заключается в том, что NTTP связан с объектом параметра шаблона со статической длительностью хранения:
Выражение id, именующее нетиповой параметр шаблона типа класса T, обозначает статический объект продолжительности хранения типа const T, известный как объект параметра шаблона, который является эквивалентом аргумента шаблона ([temp.type] ) в соответствующий аргумент шаблона после его преобразования в тип параметра шаблона ([temp.arg.nontype]). Никакие два объекта параметров шаблона не являются эквивалентными аргументам шаблона.
Тем не менее, я попытался поиграться с гораздо более простым (и надуманным) примером:
шаблон consteval const auto& make_static() { возвращаемое значение; } интервал основной() { [[maybe_unused]] const auto& i = make_static(); // (1) [[maybe_unused]] static const auto& j = make_static(); // (2) [[maybe_unused]] static constexpr auto& k = make_static(); // (3) [[maybe_unused]] constinit static auto& l = make_static(); // (4) вернуть я; } В прямом эфире
Ни одна из многих попыток не увенчалась успехом, как это видно из предоставленной связанной демо-версии. Разные составители ставят мне разные диагнозы.
Обычным шаблоном является то, что make_static() не считается постоянным выражением и возвращает ссылку на временный объект (что, насколько я понимаю, лучше, чем Гол Джейсона Тернера).
Примечание: GCC 13.2 (27 июля 2023 г.) даже жалуется на разыменование nullptr, но магистральная версия кажется более совместимой с MSVC и Clang.
Что не так с моим примером и как в этом свете работает вариант использования Джейсона Тернера?
#include #include #include #include #include #include // Какой-то алгоритм для генерации необычного std::string, возможно, во время компиляции constexpr std::string make_string(std::string_view base, const std::size_t повторение) { std::string retval; for (std::size_t count = 0; count < повторение; ++count) { ретвал += база; } возврат ретвал; } // Используйте только во время компиляции: он должен быть достаточно большим, чтобы вместить // копия строковых данных в «постоянном оцениваемом контексте» // NB: Вероятно, это неправильная формулировка выше. структура oversized_array { //статический constexpr std::size_t VeryLargeSize = 10 * 1024 * 1024; // Джейсон //пример токаря статический constexpr std::size_t VeryLargeSize = 1000; // Значение Джейсона Тернера было слишком большим для MSVC в Compiler Explorer std::array data{}; std::size_t размер; // Фактически используемый размер VeryLargeSize max. }; // Копируем содержащуюся строку в массив "достаточно большой". // Это помощник для to_right_sized_array ниже constexpr auto to_oversized_array(const std::string &str) { результат oversized_array; std::copy(str.begin(), str.end(), result.data.begin()); result.size = str.size(); вернуть результат; } // Копируем содержащуюся строку в массив того же размера. // Вызываемый объект — это лямбда, обертывающая make_string. // НО ЗА КЛАНГ шаблон consteval auto to_right_sized_array( Callable callable) { // версия Джейсона Тёрнера // constexpr auto to_right_sized_array(Callable callable) { // Кажется, так и есть // достаточно constexpr auto oversized = to_oversized_array(callable()); std::array результат; std::copy(oversized.data.begin(), std::next(oversized.data.begin(), oversized.size), результат.begin()); вернуть результат; } // Просто возвращает ссылку на «Данные» NTTP. // СУТЬ МОЕГО ВОПРОСА ЗДЕСЬ шаблон consteval const auto &make_static() { вернуть данные; } // Обертывание преобразованной из массива строки в string_view шаблон consteval auto to_string_view (Callable callable) { // std::array, поскольку NTTP — это C++20? constexpr auto &static_data = make_static(); return std::string_view{static_data.begin(), static_data.size()}; } интервал основной() { constexpr auto make_data = []() { return make_string("Привет, мир времени компиляции,", 3); }; constexpr статический автоматический просмотр = to_string_view(make_data); std::cout
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Является ли тип параметра шаблона, не являющегося типом, частью сигнатуры функции?
Anonymous » » в форуме C++ - 0 Ответы
- 13 Просмотры
-
Последнее сообщение Anonymous
-