обратная совместимость — Как мне написать свой C ++, чтобы подготовиться к модулям C ++?

Уже есть два компилятора, которые поддерживают модули C ++:

Начиная новый проект сейчас, на что я должен обратить внимание, чтобы иметь возможность использовать функцию модулей, когда она в конечном итоге будет выпущена в моем компиляторе?

Можно ли использовать модули и поддерживать совместимость со старыми компиляторами, которые его не поддерживают?

50

Решение

Уже есть два компилятора, которые поддерживают модули C ++

лязг: http://clang.llvm.org/docs/Modules.html
MS VS 2015: http://blogs.msdn.com/b/vcblog/archive/2015/12/03/c-modules-in-vs-2015-update-1.aspx

Похоже, что подход Microsoft набирает наибольшую популярность, главным образом потому, что Microsoft тратит гораздо больше ресурсов на их реализацию, чем кто-либо из лживых людей в настоящее время. Увидеть https://llvm.org/bugs/buglist.cgi?list_id=100798&query_format = продвинутый&компонент = модули&Продукт = лязг что я имею в виду, в модулях для C ++ есть несколько серьезных ошибок showtopper, тогда как модули для C или особенно Objective C выглядят гораздо более пригодными для использования в реальном коде. Крупнейший и самый важный клиент Visual Studio, Microsoft, настаивает на Модулях, потому что он решает целую тонну внутренних проблем масштабируемости сборки, а внутренний код Microsoft является одним из самых сложных C ++ для компиляции где-либо в существующем, так что вы не можете запустить любой компилятор кроме MSVC (например, удачи в получении Clang или GCC для компиляции 40k строковых функций). Поэтому приемы сборки clang, используемые Google и т. Д., Недоступны для Microsoft, и им крайне необходимо срочно исправить это, а не позже.

Это не значит, что в предложении Microsoft нет серьезных недостатков в дизайне, которые применяются на практике в больших реальных кодах. Однако Габи считает, что вы должны реорганизовать свой код для модулей, и, хотя я не согласен, я вижу, откуда он.

Начиная новый проект сейчас, на что я должен обратить внимание, чтобы иметь возможность использовать функцию модулей, когда она в конечном итоге будет выпущена в моем компиляторе?

Поскольку в настоящее время ожидается, что компилятор Microsoft будет реализовывать модули, вы должны убедиться, что ваша библиотека может использоваться во всех этих формах:

  1. Динамическая библиотека
  2. Статическая библиотека
  3. Библиотека только для заголовков

Что-то очень удивительное для многих людей, это то, что модули C ++, как ожидается, будут реализованы в настоящее время, сохраняют эти различия, так что теперь вы получаете вариант модуля C ++ для все трое из вышеупомянутого, с первым наиболее похожим на то, что люди ожидают от модуля C ++, а последним наиболее похожим на более полезный предварительно скомпилированный заголовок. Причина, по которой вам следует поддерживать эти варианты, заключается в том, что вы можете повторно использовать большую часть того же самого механизма препроцессора для поддержки модулей C ++ без особой дополнительной работы.

Более поздняя версия Visual Studio позволит связать файл определения модуля (файл .ifc) как ресурс с библиотеками DLL. Это, в конечном счете, устранит необходимость различий .lib и .dll в MSVC, вы просто предоставляете одну DLL для компилятора, и все это «просто работает» при импорте модулей, без заголовков или чего-либо еще необходимого. Это, конечно, пахнет немного как COM, но без большинства преимуществ COM.

Можно ли использовать модули в одной кодовой базе и по-прежнему поддерживать совместимость со старыми компиляторами, которые его не поддерживают?

Я предполагаю, что вы имели в виду жирный текст, вставленный выше.

Ответ, как правило, да, с еще большим удовольствием от препроцессора. #include <someheader> может превратиться в import someheader в заголовке, потому что препроцессор все еще работает как обычно. Поэтому вы можете пометить отдельные заголовки библиотек с помощью поддержки модулей C ++ примерно так:

// someheader.hpp

#if MODULES_ENABLED
#  ifndef EXPORTING_MODULE
import someheader;  // Bring in the precompiled module from the database
// Do NOT set NEED_DEFINE so this include exits out doing nothing more
#  else
// We are at the generating the module stage, so mark up the namespace for export
#    define SOMEHEADER_DECL export
#    define NEED_DEFINE
#  endif
#else
// Modules are not turned on, so declare everything inline as per the old way
#  define SOMEHEADER_DECL
#  define NEED_DEFINE
#endif

#ifdef NEED_DEFINE
SOMEHEADER_DECL namespace someheader
{
// usual classes and decls here
}
#endif

Теперь в вашем main.cpp или как угодно, вы просто делаете:

#include "someheader.hpp"

… и если у компилятора было / экспериментальное: modules / DMODULES_ENABLED, то ваше приложение автоматически использует версию библиотеки C ++ Modules вашей библиотеки. Если этого не произойдет, вы получите встроенное включение, как мы всегда делали.

Я считаю, что это минимально возможный набор изменений в вашем исходном коде, чтобы сделать ваш код готовым к использованию. Вы заметите, что я ничего не сказал о системах сборки, это потому, что я все еще отлаживаю инструментальные средства cmake, которые я написал, чтобы все эти вещи «просто работали» без проблем, и я ожидаю отладки их в течение нескольких месяцев. Ожидайте увидеть это, возможно, на конференции C ++ в следующем году или через год 🙂

25

Другие решения

Можно ли использовать модули и поддерживать совместимость со старыми компиляторами, которые его не поддерживают?

Нет, это невозможно. Это может быть возможно с использованием некоторых #ifdef магия такая:

#ifdef CXX17_MODULES
...
#else
#pragma once, #include "..." etc.
#endif

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

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

Начиная новый проект сейчас, на что я должен обратить внимание, чтобы иметь возможность использовать функцию модулей, когда она в конечном итоге будет выпущена в моем компиляторе?

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

По сути, это та же история, что и с Python3 и Python2, или, реже, с PHP7 и PHP5. Вам нужно найти баланс между тем, чтобы быть хорошим современным программистом и не раздражать людей в Debian 😉

3