Как не писать std в c
Перейти к содержимому

Как не писать std в c

  • автор:

/std (Указание стандартной версии языка)

Включите поддерживаемые функции языка C и C++ из указанной версии стандарта языка C или C++.

Синтаксис

/std:c++14
/std:c++17
/std:c++20
/std:c++latest
/std:c11
/std:c17
/std:clatest

Замечания

Параметры /std доступны в Visual Studio 2017 и более поздних версиях. Они используются для управления стандартными функциями языка программирования ISO C или C++, включенными во время компиляции кода. Эти параметры позволяют отключить поддержку некоторых новых функций языка и библиотеки: те, которые могут нарушить существующий код, соответствующий определенной версии языкового стандарта.

Компилятор Microsoft C++ в Visual Studio 2017 и более поздних версиях не поддерживает режимы стандартов C++, предшествующие C++14 ( /std:c++14 ). Такая поддержка не планируется. В качестве несовершенного обходного решения можно использовать старые наборы инструментов компилятора Visual C++, которые не реализуют функции из более поздних стандартов. Дополнительные сведения об установке и использовании старых наборов инструментов компилятора в Visual Studio см. в статье «Использование собственного многонацеливания» в Visual Studio для создания старых проектов.

Поддержка стандартов C++

Параметр /std в действии _MSVC_LANG во время компиляции C++ можно обнаружить с помощью макроса препроцессора. Дополнительные сведения см. в статье Макросы препроцессора.

Так как некоторый существующий код зависит от значения макроса __cplusplus 199711L , компилятор MSVC не изменяет значение этого макроса, если вы явно не выберете этот параметр /Zc:__cplusplus . Укажите /Zc:__cplusplus и /std параметр для задания __cplusplus соответствующего значения.

/std:c++14
Этот /std:c++14 параметр включает стандартные функции C++14, реализованные компилятором MSVC. Этот параметр используется по умолчанию для кода, скомпилированного как C++. Она доступна начиная с Visual Studio 2015 с обновлением 3.

Этот параметр отключает поддержку компилятора и стандартной библиотеки для функций, измененных или новых в более поздних версиях стандарта языка. Однако он не отключает некоторые функции C++17, уже реализованные в предыдущих выпусках компилятора MSVC. Дополнительные сведения см. в статье Соответствие стандартам языка Microsoft C/C++. Таблицы указывают, какие функции C++17 включены при указании /std:c++14 .

Следующие функции остаются включенными, если /std:c++14 указан параметр, чтобы избежать критических изменений для пользователей, которые уже приняли зависимости от функций, доступных в Visual Studio 2015 с обновлением 2 или до этого:

  • Правила для auto скобок-init-lists
  • typename в параметрах шаблона шаблона
  • Удаление триграфов
  • Атрибуты пространств имен и перечислителей
  • Символьные литералы u8

/std:c++17
Этот /std:c++17 параметр включает стандартные функции и поведение C++17. Он включает полный набор функций C++17, реализованных компилятором MSVC. Этот параметр отключает поддержку компилятора и стандартной библиотеки для новых или измененных функций после C++17. Он специально отключает изменения после C++17 в стандарте C++ и версиях рабочего черновика. Он не отключает ретроактивные обновления дефектов стандарта C++. Этот параметр доступен начиная с Visual Studio 2017 версии 15.3.

В зависимости от версии или обновления компилятора MSVC функции C++17 могут быть не полностью реализованы или полностью соответствуют параметру /std:c++17 . Общие сведения о соответствии языка C++ в Visual C++ версии выпуска см. в статье о соответствии языка Microsoft C/C++.

/std:c++20
Этот /std:c++20 параметр включает стандартные функции и поведение C++20. Доступно начиная с Visual Studio 2019 версии 16.11, он включает полный набор функций C++20, реализованных компилятором MSVC, за исключением std::format расширений форматирования C++20 , а также фабрики диапазона и адаптеры диапазона из . Эти функции по-прежнему доступны только в /std:c++latest разделе .

Параметр /std:c++20 отключает поддержку компилятора и стандартной библиотеки для новых или измененных компонентов после C++20. Он специально отключает изменения после C++20 в стандарте C++ и версиях рабочего черновика. Он не отключает ретроактивные обновления дефектов стандарта C++.

/std:c++latest
Этот /std:c++latest параметр включает все реализованные в настоящее время функции компилятора и стандартной библиотеки, предлагаемые для следующего проекта стандарта, а также некоторые текущие и экспериментальные функции. Этот параметр доступен начиная с Visual Studio 2015 с обновлением 3.

В зависимости от версии или обновления компилятора MSVC, C++17, C++20 или предлагаемых функций C++23 могут быть не полностью реализованы или полностью соответствовать при указании /std:c++latest параметра. Мы рекомендуем использовать последнюю версию Visual Studio для обеспечения максимального соответствия стандартам. Общие сведения о соответствии языка И библиотеки C++ в Visual C++ по версии выпуска см. в статье о соответствии языка Microsoft C/C++.

В версиях Visual Studio 2019 до версии 16.11 /std:c++latest необходимо включить все функции компилятора и стандартной библиотеки C++20.

Список поддерживаемых функций языка и библиотеки см. в статье «Новые возможности для C++ в Visual Studio».

Параметр /std:c++latest не включает функции, защищенные параметром /experimental , но может потребоваться для их включения.

Функции компилятора и библиотеки, включенные в /std:c++latest будущем, могут появиться в будущем стандарте C++. Неутвержденные возможности предоставляются на условиях «как есть», могут удаляться без уведомления либо в них могут вноситься критические изменения.

Поддержка стандартов C

Вы можете вызвать компилятор Microsoft C с помощью /TC параметра или /Tc компилятора. Он используется по умолчанию для кода с .c расширением файла, если не переопределяется параметром или /Tp параметром /TP . Компилятор C по умолчанию (т. е. компилятор, когда /std:c11 или /std:c17 не указан) реализует ANSI C89, но включает несколько расширений Майкрософт, некоторые из которых являются частью ISO C99. Некоторые расширения Майкрософт в C89 могут быть отключены с помощью /Za параметра компилятора, но другие остаются в силе. Невозможно указать строгое соответствие C89. Компилятор не реализует несколько обязательных функций C99, поэтому невозможно указать соответствие C99.

/std:c11
Параметр /std:c11 включает соответствие ISO C11. Она доступна начиная с Visual Studio 2019 версии 16.8.

/std:c17
Параметр /std:c17 включает соответствие ISO C17. Она доступна начиная с Visual Studio 2019 версии 16.8.

Так как новый препроцессор необходим для поддержки этих стандартов, /std:c11 /std:c17 параметры компилятора задают этот /Zc:preprocessor параметр автоматически. Если вы хотите использовать традиционный (устаревший) препроцессор для C11 или C17, необходимо явно задать параметр компилятора /Zc:preprocessor- . /Zc:preprocessor- Установка параметра может привести к непредвиденному поведению и не рекомендуется.

Во время выпуска и до Visual Studio 2019 версии 16.10 библиотеки Windows SDK и UCRT, установленные Visual Studio, пока не поддерживают код C11 и C17. Требуется обновленная версия пакета SDK для Windows и UCRT. Дополнительные сведения и инструкции по установке см. в разделе «Установка C11 и C17» в Visual Studio.

При указании /std:c11 или /std:c17 MSVC поддерживает все функции C11 и C17, необходимые стандартам. /std:c17 Параметры /std:c11 компилятора обеспечивают поддержку этих функций:

В интегрированной среде разработки используются параметры C для IntelliSense и выделение кода, когда исходные файлы имеют .c расширение файла или при указании /TC параметра компилятора. /Tc В настоящее время IntelliSense в C выделяет ключевое слово _Alignas , _Alignof _Noreturn и _Static_assert , но не эквивалентные макросы, определенные в стандартных заголовках: alignas , alignof noreturn и static_assert .

Так как C17 в значительной степени является выпуском исправления ошибок ISO C11, поддержка MSVC для C11 уже включает все соответствующие отчеты о дефектах. Нет различий между версиями C11 и C17, за исключением макроса __STDC_VERSION__ . Он расширяется до 201112L C11 и 201710L для C17.

Компилятор не поддерживает большинство необязательных функций ISO C11. Некоторые из этих дополнительных функций C11 были обязательными функциями C99, которые MSVC не реализованы по архитектурным причинам. Макросы теста функций можно использовать для __STDC_NO_VLA__ обнаружения уровней поддержки компилятора для отдельных функций. Дополнительные сведения о предопределенных макросах C см. в разделе «Предопределенные макросы».

  • Нет поддержки многопоточных, атомарных или сложных чисел.
  • aligned_alloc Поддержка отсутствует из-за реализации кучи Windows. Альтернативой является использование _aligned_malloc .
  • Поддержка отчета о дефектах 400 в настоящее время не поддерживается realloc , так как это изменение приведет к разрыву ABI.
  • Поддержка массива переменной длины (VLA) не запланирована. VLA предоставляют векторы атак, аналогичные gets устаревшим и запланированным для удаления.

/std:clatest
Параметр /std:clatest ведет себя как /std:c++latest переключатель для компилятора C++. Этот коммутатор включает все реализованные в настоящее время функции компилятора и стандартной библиотеки, предлагаемые для следующего проекта стандарта C, а также некоторые текущие и экспериментальные функции.

Дополнительные сведения см. в разделе о функциях стандартной библиотеки C для соответствия языка Microsoft C/C++.

Установка данного параметра компилятора в среде разработки Visual Studio

  1. Откройте диалоговое окно Страницы свойств проекта. Подробнее см. в статье Настройка компилятора C++ и свойств сборки в Visual Studio.
  2. Выберите страницу свойств>конфигурации C/C++>Language.
  3. В C++ Language Standard (или для C, C Language Standard) выберите языковой стандарт для поддержки из раскрывающегося списка, а затем нажмите кнопку «ОК» или » Применить«, чтобы сохранить изменения.

Руководство. Импорт стандартной библиотеки C++ с помощью модулей из командной строки

Узнайте, как импортировать стандартную библиотеку C++ с помощью модулей библиотекИ C++. Это приводит к более быстрой компиляции и более надежной, чем использование файлов заголовков или блоков заголовков или предварительно скомпилированных заголовков (PCH).

В этом руководстве описано:

  • Как импортировать стандартную библиотеку в виде модуля из командной строки.
  • Преимущества производительности и удобства использования модулей.
  • Два стандартных модуля библиотеки std и std.compat разница между ними.

Необходимые компоненты

Для работы с этим руководством требуется Visual Studio 2022 17.5 или более поздней версии.

Общие сведения о модулях стандартной библиотеки

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

Теперь можно импортировать стандартную библиотеку в виде модуля вместо танга файлов заголовков. Это гораздо быстрее и надежнее, чем в том числе файлы заголовков или блоки заголовков или предварительно скомпилированные заголовки (PCH).

Стандартная библиотека C++23 содержит два именованных модуля: std и std.compat :

  • std экспортирует объявления и имена, определенные в стандартном пространстве std имен библиотеки C++, например std::vector . Он также экспортирует содержимое заголовков оболочки C, таких как и , которые предоставляют такие функции, как std::printf() . Функции C, определенные в глобальном пространстве имен, например ::printf() , не экспортируются. Это улучшает ситуацию, когда в том числе заголовок оболочки C, например stdio.h , содержит такие файлы заголовков C, как и в глобальных версиях пространства имен C. Это не проблема при импорте std .
  • std.compat экспортирует все и std добавляет глобальные пространства имен среды выполнения C, такие как ::printf , ::fopen , ::size_t и ::strlen т. д. Модуль std.compat упрощает работу с базами кода, которые ссылаются на многие функции и типы среды выполнения C в глобальном пространстве имен.

Компилятор импортирует всю стандартную библиотеку при использовании import std; или import std.compat; выполняет ее быстрее, чем при вводе в один файл заголовка. Это быстрее, чтобы привести всю стандартную библиотеку с import std; (или import std.compat ) к #include , например.

Так как именованные модули не предоставляют макросы, макросы, например assert , errno , offsetof и va_arg другие, недоступны при импорте std или std.compat . Рекомендации по обходным решениям см. в стандартной библиотеке именованных модулей.

Сведения о модулях C++

Файлы заголовков — это способ совместного использования объявлений и определений между исходными файлами в C++. Перед модулями стандартной библиотеки вы будете включать часть стандартной библиотеки, необходимую для директивы, например #include . Файлы заголовков являются хрупкими и сложными, так как их семантика может изменяться в зависимости от порядка их включения или определения определенных макросов. Они также медленно компилируются, так как они повторно обрабатывается каждым исходным файлом, который включает их.

В C++20 представлен современный альтернативный вариант, называемый модулями. В C++23 мы смогли использовать поддержку модулей, чтобы представить именованные модули для представления стандартной библиотеки.

Как и файлы заголовков, модули позволяют совместно использовать объявления и определения в исходных файлах. Но в отличие от файлов заголовков модули не хрупки и проще создавать их, так как их семантика не изменяется из-за определений макросов или порядка их импорта. Компилятор может обрабатывать модули гораздо быстрее, чем может обрабатывать #include файлы, а также использовать меньше памяти во время компиляции. Именованные модули не предоставляют определения макросов или сведения о частной реализации.

Подробные сведения о модулях см. в разделе «Обзор модулей в C++ В этой статье также рассматривается использование стандартной библиотеки C++ в качестве модулей, но используется более старый и экспериментальный способ его выполнения».

В этой статье демонстрируется новый и лучший способ использования стандартной библиотеки. Дополнительные сведения о альтернативных способах использования стандартной библиотеки см. в статье «Сравнение единиц заголовков, модулей и предварительно скомпилированных заголовков».

Импорт стандартной библиотеки с помощью std

В следующих примерах показано, как использовать стандартную библиотеку в качестве модуля с помощью компилятора командной строки. Сведения о том, как это сделать в интегрированной среде разработки Visual Studio, см. в разделе «Сборка модулей стандартной библиотеки ISO C++23».

Инструкция import std; или import std.compat; импорт стандартной библиотеки в приложение. Но сначала необходимо скомпилировать стандартные именованные модули библиотеки в двоичную форму. Ниже показано, как это сделать.

Пример. Создание и импорт std

  1. Откройте командную строку собственных средств x86 для VS: в меню «Пуск» Windows введите собственный код x86, а в списке приложений должен появиться запрос. Убедитесь, что запрос предназначен для Visual Studio 2022 версии 17.5 или выше. Если вы используете неправильную версию запроса, вы получите ошибки. Примеры, используемые в этом руководстве, предназначены для оболочки CMD.
  2. Создайте каталог, например %USERPROFILE%\source\repos\STLModules и сделайте его текущим каталогом. Если у вас нет доступа на запись, вы получите ошибки во время компиляции.
  3. Скомпилируйте именованный модуль с помощью следующей std команды:
cl /std:c++latest /EHsc /nologo /W4 /c "%VCToolsInstallDir%\modules\std.ixx" 
  • std.ifc — это скомпилированное двоичное представление именованного интерфейса модуля, который компилятор обращается к процессу инструкции import std; . Это артефакт только во время компиляции. Он не отправляется с приложением.
  • std.obj содержит реализацию именованного модуля. Добавьте std.obj в командную строку при компиляции примера приложения для статического связывания функциональных возможностей, используемых из стандартной библиотеки в приложение.

Параметры командной строки в этом примере:

Коммутатор Значение
/std:c++:latest Используйте последнюю версию стандарта языка C++ и библиотеки. Хотя поддержка модулей доступна в разделе /std:c++20 , вам нужна последняя стандартная библиотека, чтобы получить поддержку стандартных именованных модулей библиотеки.
/EHsc Используйте обработку исключений C++ за исключением функций, помеченных extern «C» .
/W4 Использование /W4 обычно рекомендуется, особенно для новых проектов, так как он включает все уровни 1, уровень 2, уровень 3 и большинство предупреждений уровня 4 (информационные), которые могут помочь вам поймать потенциальные проблемы рано. Он, по сути, предоставляет предупреждения, подобные lint, которые могут помочь обеспечить наименьшие возможные дефекты кода.
/c Скомпилируйте без связывания, так как мы просто создадим двоичный именованный интерфейс модуля на этом этапе.

Вы можете управлять именем файла объекта и именем именованного файла интерфейса модуля с помощью следующих переключателей:

  • /Fo задает имя файла объекта. Например, /Fo:»somethingelse» . По умолчанию компилятор использует то же имя для файла объекта, что и исходный файл модуля ( .ixx ). В примере имя файла объекта по умолчанию является std.obj тем, что мы компилируем файл std.ixx модуля.
  • /ifcOutput задает имя именованного файла интерфейса модуля ( .ifc ). Например, /ifcOutput «somethingelse.ifc» . По умолчанию компилятор использует то же имя для файла интерфейса модуля ( .ifc ), что и исходный файл модуля ( .ixx ). В примере созданный ifc файл по умолчанию является std.ifc по умолчанию, так как мы компилируем файл std.ixx модуля.
// requires /std:c++latest import std; int main() < std::cout v; for (const auto& e : v) < std::cout > 
cl /c /std:c++latest /EHsc /nologo /W4 /reference "std=std.ifc" importExample.cpp link importExample.obj std.obj 

В этом примере не требуется указывать /reference «std=std.ifc» в командной строке, так как компилятор автоматически ищет .ifc файл, соответствующий имени модуля, заданному инструкцией import . Когда компилятор обнаруживает import std; его, может ли он находиться std.ifc в том же каталоге, что и исходный код. .ifc Если файл находится в каталоге, отличном от исходного кода, используйте параметр компилятора /reference для ссылки на него. В этом примере компиляция исходного кода и связывание реализации модуля с приложением являются отдельными шагами. Они не должны быть. Вы можете использовать cl /std:c++latest /EHsc /nologo /W4 /reference «std=std.ifc» importExample.cpp std.obj для компиляции и связывания на одном шаге. Но это может быть удобно для сборки и связывания отдельно, так как затем необходимо создать стандартную библиотеку с именем модуля один раз, а затем вы можете ссылаться на него из проекта или из нескольких проектов на шаге ссылки сборки. Если вы создаете один проект, вы можете объединить шаги по созданию std стандартной библиотеки с именем модуля и этапу создания приложения, добавив «%VCToolsInstallDir%\modules\std.ixx» в командную строку. Поместите его перед любыми .cpp файлами, которые используют std модуль. По умолчанию имя выходного исполняемого файла берется из первого входного файла. Используйте параметр компилятора, чтобы указать нужное /Fe имя исполняемого файла. В этом руководстве показано, как скомпилировать именованный std модуль как отдельный шаг, так как необходимо создать стандартную библиотеку с именем модуля один раз, а затем можно ссылаться на него из проекта или из нескольких проектов. Но может быть удобно создать все вместе, как показано в этой командной строке:

cl /FeimportExample /std:c++latest /EHsc /nologo /W4 "%VCToolsInstallDir%\modules\std.ixx" importExample.cpp 

Учитывая предыдущую командную строку, компилятор создает исполняемый файл с именем importExample.exe . При запуске он создает следующие выходные данные:

Import the STL library for best performance 555 

Импорт стандартной библиотеки и глобальных функций C с помощью std.compat

Стандартная библиотека C++ включает стандартную библиотеку ISO C. Модуль std.compat предоставляет все функциональные возможности std модуля, например std::vector , std::cout , std::printf и std::scanf т. д. Но она также предоставляет версии глобального пространства имен таких функций, как ::printf , ::scanf , ::fopen и ::size_t т. д.

Именованный std.compat модуль — это уровень совместимости, предоставляемый для упрощения переноса существующего кода, который относится к функциям среды выполнения C в глобальном пространстве имен. Если вы хотите избежать добавления имен в глобальное пространство имен, используйте import std; . Если вам нужно упростить миграцию базы кода, использующую множество неквалифицированных (глобальное пространство имен) функций среды выполнения C, используйте import std.compat; . Это обеспечивает имена среды выполнения C глобального пространства имен, чтобы вам не нужно было указывать все глобальные имена. std:: Если у вас нет существующего кода, использующего функции среды выполнения C глобального пространства имен, вам не нужно использовать import std.compat; . Если вы вызываете только несколько функций среды выполнения C в коде, возможно, лучше использовать import std; и указать несколько имен глобального пространства имен C, которым он std:: нужен. Например, std::printf() . Если при попытке компиляции кода возникает ошибка error C3861: ‘printf’: identifier not found , рассмотрите возможность import std.compat; импорта функций среды выполнения C глобального пространства имен.

Пример. Создание и импорт std.compat

Прежде чем использовать import std.compat; , необходимо скомпилировать файл интерфейса модуля, найденный в форме std.compat.ixx исходного кода. Visual Studio поставляет исходный код модуля, чтобы можно было скомпилировать модуль с помощью параметров компилятора, соответствующих проекту. Действия аналогичны созданию именованного std модуля. Именованный std модуль создается сначала, так как std.compat зависит от него:

  1. Откройте командную строку собственных средств для VS: в меню «Пуск» Windows введите собственный код x86 и в списке приложений должна появиться строка. Убедитесь, что запрос предназначен для Visual Studio 2022 версии 17.5 или выше. Если вы используете неправильную версию запроса, вы получите ошибки компилятора.
  2. Создайте каталог, чтобы попробовать этот пример, например %USERPROFILE%\source\repos\STLModules , и сделать его текущим каталогом. Если вы выберете каталог, в который у вас нет доступа на запись, вы получите ошибки.
  3. std Скомпилируйте и std.compat именованные модули с помощью следующей команды:

cl /std:c++latest /EHsc /nologo /W4 /c "%VCToolsInstallDir%\modules\std.ixx" "%VCToolsInstallDir%\modules\std.compat.ixx" 
  • std.ifc — это скомпилированный двоичный именованный интерфейс модуля, который компилятор обращается к процессу инструкции import std; . Компилятор также обращается к std.ifc процессу, так как std.compat выполняет сборку std import std.compat; . Это артефакт только во время компиляции. Он не отправляется с приложением.
  • std.obj содержит реализацию стандартной библиотеки.
  • std.compat.ifc — это скомпилированный двоичный именованный интерфейс модуля, который компилятор обращается к процессу инструкции import std.compat; . Это артефакт только во время компиляции. Он не отправляется с приложением.
  • std.compat.obj содержит реализацию. Однако большая часть реализации предоставляется std.obj . Добавьте std.obj в командную строку при компиляции примера приложения для статического связывания функциональных возможностей, используемых из стандартной библиотеки в приложение.

Вы можете управлять именем файла объекта и именем именованного файла интерфейса модуля с помощью следующих переключателей:

  • /Fo задает имя файла объекта. Например, /Fo:»somethingelse» . По умолчанию компилятор использует то же имя для файла объекта, что и исходный файл модуля ( .ixx ). В этом примере имена файлов объектов и по умолчанию являются std.obj и std.compat.obj по умолчанию, так как компилируем файлы std.ixx модуля и std.compat.obj .
  • /ifcOutput задает имя именованного файла интерфейса модуля ( .ifc ). Например, /ifcOutput «somethingelse.ifc» . По умолчанию компилятор использует то же имя для файла интерфейса модуля ( .ifc ), что и исходный файл модуля ( .ixx ). В этом примере созданные ifc файлы по умолчанию являются std.ifc и std.compat.ifc по умолчанию, так как мы компилируем файлы std.ixx модуля и std.compat.ixx .
import std.compat; int main() < printf("Import std.compat to get global names like printf()\n"); std::vectorv; for (const auto& e : v) < printf("%i", e); >> 
cl /std:c++latest /EHsc /nologo /W4 stdCompatExample.cpp link stdCompatExample.obj std.obj std.compat.obj 

Нам не нужно указывать std.compat.ifc в командной строке, так как компилятор автоматически ищет .ifc файл, соответствующий имени модуля в инструкции import . Когда компилятор обнаруживает import std.compat; его std.compat.ifc , так как мы помещаем его в тот же каталог, что и исходный код, который позволяет нам указать его в командной строке. .ifc Если файл находится в каталоге, отличном от исходного кода или имеет другое имя, используйте /reference переключатель компилятора для ссылки на него. При импорте std.compat необходимо связаться с обоими std.compat и std.obj потому, что std.compat использует код в std.obj . Если вы создаете один проект, вы можете объединить шаги по созданию std именованных модулей и std.compat стандартной библиотеки, добавив «%VCToolsInstallDir%\modules\std.ixx» и «%VCToolsInstallDir%\modules\std.compat.ixx» (в этом порядке) в командную строку. В этом руководстве показано создание модулей стандартной библиотеки как отдельный шаг, так как необходимо создать только стандартные именованные модули библиотеки один раз, а затем можно ссылаться на них из проекта или из нескольких проектов. Но если их удобно создавать одновременно, обязательно поместите их перед любыми .cpp файлами, которые используют их, и укажите /Fe имя встроенного, exe как показано в этом примере:

cl /c /FestdCompatExample /std:c++latest /EHsc /nologo /W4 "%VCToolsInstallDir%\modules\std.ixx" "%VCToolsInstallDir%\modules\std.compat.ixx" stdCompatExample.cpp link stdCompatExample.obj std.obj std.compat.obj 

В этом примере компиляция исходного кода и связывание реализации модуля с приложением являются отдельными шагами. Они не должны быть. Вы можете использовать cl /std:c++latest /EHsc /nologo /W4 stdCompatExample.cpp std.obj std.compat.obj для компиляции и связывания на одном шаге. Но это может быть удобно для сборки и связывания отдельно, так как затем необходимо создать стандартные библиотеки именованных модулей один раз, а затем вы можете ссылаться на них из проекта или из нескольких проектов на шаге ссылки сборки. Предыдущая команда компилятора создает исполняемый файл с именем stdCompatExample.exe . При запуске он создает следующие выходные данные:

Import std.compat to get global names like printf() 555 

Рекомендации по использованию стандартной библиотеки с именем модуля

Управление версиями именованных модулей совпадает с заголовками. Файлы .ixx именованного модуля устанавливаются вместе с заголовками, например «%VCToolsInstallDir%\modules\std.ixx : который разрешается C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.38.33130\modules\std.ixx в версию средств, используемых во время записи. Выберите версию именованного модуля так же, как и версию файла заголовка для использования каталогом, который вы ссылаетесь на них.

Не смешивайте и не сопоставляйте блоки заголовков и именованные модули. Например, не import ; import std; и в одном файле.

Не смешивайте и не сопоставляйте файлы заголовков стандартной библиотеки C++ и именованные модули std или std.compat . Например, не #include import std; и в одном файле. Однако вы можете включить заголовки C и импортировать именованные модули в один и тот же файл. Например, можно import std; и #include в одном файле. Просто не включайте стандартную версию библиотеки C++ .

Вам не нужно защищаться от импорта модуля несколько раз. Т. е. в модулях не требуются #ifndef охранники заголовков стилей. Компилятор знает, когда он уже импортировал именованный модуль и игнорирует повторяющиеся попытки сделать это.

Если необходимо использовать assert() макрос, то #include .

Если необходимо использовать errno макрос, #include . Так как именованные модули не предоставляют макросы, это обходное решение, если необходимо проверка для ошибок , например.

Макросы, такие как NAN INFINITY , и INT_MIN определяются с помощью которых можно включить. Однако, если вы import std; можете использовать numeric_limits::quiet_NaN() и numeric_limits::infinity() вместо NAN INFINITY него, а std::numeric_limits::min() не INT_MIN .

Итоги

В этом руководстве вы импортировали стандартную библиотеку с помощью модулей. Далее вы узнаете о создании и импорте собственных модулей в учебнике по именованным модулям в C++.

Ввод строки c++ с пробелами [дубликат]

getline дочитывает остаток первой строки, все что идет после числа. Даже если там ничего нет, кроме символа переноса строки.

Например, если ввести 1,2 , то в getline попадет ,2 .

Возможных решений несколько:

  • Вызвать getline два раза. Первый раз проверить, что получилась пустая строка, и если нет, выдать ошибку, что в первой строке после числа мусор. А результат второго вызова уже использовать.
  • Проигноировать оставшуюся часть первой строки, вот так: cin.ignore(std::numeric_limits::max(),’\n’); .

Отслеживать
ответ дан 14 апр 2022 в 21:28
HolyBlackCat HolyBlackCat
28k 3 3 золотых знака 27 27 серебряных знаков 40 40 бронзовых знаков

  • c++
  • строки
    Важное на Мете
Связанные
Похожие

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.4.30.8466

Пространство имен (using namespace std;)

Очень часто в интернете вижу как многие программисты усердно пишут везде программы используя в коде std:: . Зачем они это делают? Почему нельзя просто использовать using namespace std; перед программой, так же удобнее и код начинает «дышать». Или это плохой тон и стоит переучиваться на использование std:: непосредственно в коде программы?

Отслеживать
31.2k 13 13 золотых знаков 98 98 серебряных знаков 159 159 бронзовых знаков
задан 11 апр 2015 в 14:23
347 1 1 золотой знак 3 3 серебряных знака 6 6 бронзовых знаков

Добро пожаловать в мир крестов. Я не знаю как ответить на этот вопрос. По поводу дышашего кода из за одного using объявления вы преувеличиваете.

11 апр 2015 в 14:24

Так почему же преувеличиваю? Грубо говоря что я потратил всего одну строчку для using namespace std; и что у меня во всём коде можно сказать на каждой строчке красуется std. По факту очень даже ощутимая разница если визуально оценивать код. Может это конечно глупости и не стоит по поводу этого заморачиваться. Но пока что, этот момент мне не понятен)

11 апр 2015 в 14:28

Вы понимаете что в C например вообще нет пространств имен? А в С++11 директива using может быть использована например для создания шаблонных синонимов или вместо typedef для создания синонима типа. Короче я не знаю как ответить на вопрос почему какие-то люди где-то там далеко вместо using namepace std; пишут std::cout . Может им так нравится или они просто дураки? Откуда мне знать точную причину?

11 апр 2015 в 14:40
Вот ещё по теме: ru.stackoverflow.com/q/201310/10105
11 апр 2015 в 16:03
А что такое «дышащий код»?
26 апр 2015 в 6:31

5 ответов 5

Сортировка: Сброс на вариант по умолчанию

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

Явное указание пространства имён — это избавление от потенциальных проблем в будущем. Положим, вы подключили через using namespace два пространства имён. Всё замечательно, кратко, красиво.

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

В лучшем случае ваш код не соберётся. Может упасть. А может так получиться, что ваш код перестанет работать у клиента в 1% случаев. Всё может быть.

Отлавливать и исправлять подобные проблемы мучительно больно.

Насколько это важно конкретно для вас — решать вам. Если у вас простой проектик и от силы пара сторонних библиотек (или вообще только стандартная библиотека), то можно не заморачиваться с явным указанием пространств имён. Если проект огромный, с десятками библиотек, то может оказаться более удобным (и наглядным) всегда указывать пространства имён.

Банальный пример: положим, вы пользуетесь только стандартной библиотекой и boost, поэтому решили везде писать:

using namespace std; using namespace boost; 

. а теперь выходит новая версия стандартной библиотеки, в которой из boost перетащено много классов. И внезапно ваш код больше не компилируется.

В других языках другие традиции. Например, в C# почти всегда пишут краткие имена классов, и только в случае конфликтов явно указывают пространство имён или используют алиасы. Язык немного отличается: там нет функций вне классов. Это позволяет меньше терять читаемость и реже натыкаться на неожиданные конфликты.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *