Что нового?


Команда Visual C++ рада сообщить, что в Visual Studio 2017 было существенно улучшено качество реализации модулей C++ согласно технической спецификации; также мы добавили возможность подключать Стандартную Библиотеку C++ через интерфейсы модулей. Эти интерфейсы, как и поддержка модулей компилятором, являются экспериментальной разработкой и будут развиваться в соответствии с процессом стандартизации.

Начало работы


Поддержка модулей Стандартной Библиотеки реализована в Visual Studio начиная с версии 2017 RTM. Эта функция на данный момент является опциональной и по умолчанию отключена. В будущих версиях модули будут устанавливаться автоматически вместе с заголовками Стандартной Библиотеки. Вам нужно лишь выбрать эту опцию при установке или обновлении поддержки C++.

Picture 5



Если вы уже установили VS 2017, но не устанавливали модули, это легко исправить. Просто запустите установщик еще раз и выберите соответствующие компоненты.

Picture 23


Проверка правильности установки


Чтобы проверить, настроена ли ваша копия VS 2017 для поддержки модулей, скомпилируйте и запустите приведенную ниже программу (назовите ее, например, test-vs2017-slm.cxx) из командной строки разработчика. Поскольку модули на данный момент являются экспериментальной функцией, их поддержка пока еще очень слабо реализована в среде VS.

import std.core; 
  
int main() { 
    using namespace std; 
    vector<string> v { "Plato", "Descartes", "Bacon" }; 
    copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n")); 
} 

При компиляции этого кода с командой

cl /experimental:module /EHsc /MD /std:c++latest test-vs2017-slm.cxx

на выходе должен получиться исполняемый файл (test-vs2017-slm.exe), который при запуске распечатает слова «Plato», «Descartes» и «Bacon» — каждое отдельной строкой.

Ключ компилятора для подключения модулей Стандартной Библиотеки


Необходимо добавить ключ /MD при компиляции исходного файла, чтобы подключить модули Стандартной Библиотеки. Ключ /MD инициализирует динамическую библиотеку времени выполнения C (CRT). В режиме отладки следует использовать ключ /MDd.

Если вы забыли указать ключ /MD (или /MDd в режиме отладки), линковщик выдаст ряд предупреждений и ошибку линковки LNK2019, говорящую о наличии неразрешенных внешних символов.

Никаких других ключей для использования модулей Стандартной Библиотеки не требуется. Эти модули могут применяться только для использования с библиотеками импорта DLL Универсальной библиотеки CRT (UCRT).

Подключение модулей Стандартной Библиотеки из среды разработки VS


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

1. Откройте окно «Свойства» (Properties) проекта:

Picture 10


2. Перейдите в раздел «Свойства конфигурации» (Configuration Properties) -> C/C++ -> «Генерация кода» (Code Generation) и убедитесь, что у вас выбрана библиотека Multithreaded Debug DLL или Multithreaded DLL (для режимов отладки и релиза соответственно). Эти библиотеки выбраны по умолчанию для новых проектов, так что, если вы ничего не меняли, никаких проблем возникнуть не должно.

Picture 22


3. Зайдите в раздел «Свойства конфигурации» (Configuration Properties) -> C/C++ -> «Язык» (Language) и убедитесь, что включена поддержка стандарта C++17. Если это не так, выберите из выпадающего списка стандарт C++17 или последний проект стандарта C++ (C++ Latest Draft Standard) для конфигураций, которые вы планируете использовать.

Picture 15


4. Впишите команду /experimental:module /module:stdIfcDir "$(VCToolsInstallDir_150)ifc\$(PlatformTarget)" в разделе «Свойства конфигурации» (Configuration Properties) -> C/C++ -> «Командная строка» (Command Line), чтобы включить поддержку модулей для текущего проекта. Обратите внимание, что данный шаг будет упразднен в будущих версиях VS 2017: среда будет сама указывать расположение файлов модулей (задается параметром /module:stdIfcDir) при включении опции поддержки модулей C++.

Picture 17



После этих действий сборка и запуск тестовой программы должны пройти успешно — программа распечатает имена трех философов.

Picture 20


Изменение синтаксиса экспорта модулей


На съезде комитета по стандартизации C++ в ноябре 2016 года было принято решение об изменении синтаксиса экспорта модулей (см. Проблема модулей N1).

Было:

export module Bank;

Стало:

export import Bank;

Настоящая версия Visual C++ учитывает это изменение, но также позволяет использовать и старый синтаксис, предупреждая о переходе к устаревшему варианту. Комитет по C++ рассматривает возможность присвоения старому синтаксису нового значения, несовместимого с прежним. Мы призываем вас использовать новый синтаксис; поддержка старого синтаксиса будет прекращена в целях соответствия проекту технической спецификации по модулям согласно поправкам комитета ISO C++.

Модули Стандартной Библиотеки (экспериментальная функция)


Ключевым нововведением в версии VS2017 RTM стала поддержка подключения Стандартной Библиотеки C++ посредством модулей. Это экспериментальный инструмент, описанный в предложении по C++ о Модулях Стандартной Библиотеки. В текущей версии модули организованы следующим образом:

  • std.regex предоставляет доступ к содержимому заголовка <regex>
  • std.filesystem предоставляет доступ к содержимому заголовка <experimental/filesystem>
  • std.memory предоставляет доступ к содержимому заголовка <memory>
  • std.threading предоставляет доступ к содержимому заголовков <atomic>, <condition_variable>, <future>, <mutex>, <shared_mutex>, <thread>
  • std.core предоставляет доступ к прочему содержимому Стандартной Библиотеки C++

Чтобы использовать эти модули в своей программе, просто впишите в верхнем уровне исходного файла инструкцию import M, где M — название модуля из списка выше. См. тестовый пример.

Если вы хотите использовать модули для включения заголовков не из Стандартной Библиотеки, сгенерировать модули Стандартной Библиотеки можно с помощью ключей /module:name (см. исходную заметку по модулям C++) и /module:export. Если ваш проект зависит от других библиотек и вы хотите попробовать собрать код совсем без заголовков, упаковать заголовки из таких библиотек можно тем же самым способом.

Новые версии VS будут в большей степени соответствовать предложению по модулям Стандартной Библиотеки.

Призыв к действию


Скачайте Visual Studio 2017 и опробуйте модули со своими C++-проектами и программами. Для начала можно просто заменить в исходных файлах все команды #include стандартных заголовков для контейнеров и алгоритмов на import std.core и добавить ключи компиляции /experimental:module и /MD или /MDd (в режиме отладки) к определению сборки. О результатах сообщайте нам.

В заключение


Как всегда, мы будем рады вашим отзывам. Свои комментарии присылайте по адресу visualcpp@microsoft.com либо оставляйте в Twitter @visualc или на странице Facebook Microsoft Visual Cpp.

О прочих проблемах, связанных с использованием среды MSVC в VS 2017, можно сообщить с помощью функции Сообщить о проблеме (Report a Problem) из установщика или из самой среды Visual Studio. Свои предложения оставляйте на сайте UserVoice. Спасибо!
Поделиться с друзьями
-->

Комментарии (16)


  1. hdfan2
    12.05.2017 12:12
    +9

    export import Bank;

    Шизофрения на марше. В чём смысл было менять module на import? Чтобы не делать module зарезервированным словом? В указанном документе не нашёл никакого объяснения.


    1. mapron
      12.05.2017 15:58
      +1

      Я так понял, что это относится к экспортируемым включениям других модулей. Как по мне, смотрится куда более логично.
      Если мне нужен приватный «инклюд»
      я пишу просто
      import Blank;
      А если мне его еще и наружу надо отдать тем, кто будет мной пользоваться:
      export import Blank;
      ИМХО интуитивнее.


  1. alexeykuzmin0
    12.05.2017 12:15
    +1

    А появилась ли поддержка модулей со стороны IDE (а не компилятора)? А то модули — это, конечно, круто, но писать без IntelliSense и прочего я и в блокнотике могу.


    1. mapron
      12.05.2017 15:59

      Судя по статье — пока нет.


  1. nkozhevnikov
    12.05.2017 13:28

    Я, может, слишком глуп, но для чего вообще нужны модули в C++?


    1. sborisov
      12.05.2017 14:19
      +3

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


      1. mapron
        12.05.2017 16:00

        Например, вставил несколько стандартных инклюдов типа iostream — и хоп! компилятору нужно уже мегабайтный файл процессить. А так у него уже готовые AST будут.
        По сути, это эволюционное развитие идеи preprocessed headers, но на уровне одного хедера)




  1. Elsedar
    12.05.2017 16:06

    А со статической линковкой CRT(/MT /MTd) пока не работает?


  1. mapron
    12.05.2017 16:06
    +1

    У меня вопрос к тем, кто их уже успел поковырять: как там обстоят дела с параллельной сборкой?
    Допустим у меня такие файлы:
    foo.cpp
    bar.cpp
    module.hpp
    Модуль используется в обоих foo.cpp и bar.cpp. Соответственно, когда компилятор будет процессить модуль, ему нужно будет где-то сохранить результат. Я правильно понимаю, что до того как для module.hpp будет скомпилено бинарное представление (AST или что там), то нельзя начинать компилить foo или bar? ну а иначе же они могут одновременно попытаться получить/скомпилить данные module.hpp?

    upd: кажется, да, понял, для компиляции по крайней мере msvc нужно указывать уже скомпиленные модули


  1. ElectroGuard
    13.05.2017 00:11
    -1

    30 лет думали, думали и наконец придумали то, что в pascal/delphi было давным-давно :) браво! верной дорогой. мы делаем проще. сам delphi и используем.


    1. Jamdaze
      13.05.2017 11:13

      В каждой теме про ц++ найдётся дурачёк который использую <свойЛюбимыйЯзычёк>.


      1. ElectroGuard
        13.05.2017 15:39
        +1

        Удивительно другое, что ваш 'умный' язык постепенно превращается в наш 'глупый'. Странно как-то, правда?


        1. Andrey2008
          13.05.2017 15:45
          +2

          Да, но без потери производительности. В любой момент можно использовтаь те технологии, чтобы получить эффективность Си.


  1. Error1024
    13.05.2017 05:46
    +2

    export import Bank;

    Давайте тогда ещё
    import export Bank;


    Я понимаю, C++ сложный язык, но почему нельзя сделать хоть тут без шизофрении :(