Решает ли стандарт модуля для C ++ проблему сокрытия личных данных от абонентов? - PullRequest
2 голосов
/ 11 марта 2019

В C ++ модули стандартизируются для решения проблемы #include bloat среди прочего. Компиляторы в C ++ должны анализировать слишком много.

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

Устраняет ли эта проблема стандарт следующего модуля?

Пример:

class GLWin {
private:
  GLFWwindow* win;
  glm::mat4 projection;
  ...
};

Объект, содержащий указатель на внутреннюю реализацию, может быть отделен пустой декларацией, то есть:

класс GLFWwindow;

но если для производительности мы включаем объект mat4 в окно, то нам нужно знать размер, который в настоящее время означает включение определения, добавление заголовочного файла, который часто огромен из-за каскадных включений. Есть ли механизм в модулях, который скрывает детали и позволяет зарезервировать правильное количество места для объекта, оставляя его непрозрачным, как указатель?

Ответы [ 2 ]

7 голосов
/ 11 марта 2019

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

Что делает модуль, так это делает:

  1. Когда вы получаете эти виды рекурсивных «включений», они на самом деле не выставляют эти внутренние компоненты во внешний код. В вашем примере предположим, что glm::mat4 происходит от модуля с именем GLM. Ваш модуль, который объявляет GLFWin, будет иметь import GLM, так как ему нужны эти определения для работы. Однако это детали реализации, поэтому вы не будете делать export import GLM.

    Теперь кто-то другой приходит и импортирует ваш модуль. Чтобы выполнить этот импорт, компилятор должен прочитать модуль GLM. Но поскольку ваш модуль не экспортирует GLM, код, который импортирует ваш модуль , не может использовать его . То есть они сами не могут использовать glm::mat4 или что-либо еще, если только они сами не импортируют этот модуль.

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

  2. Этот импорт не такой болезненный. Предполагается, что результатом компиляции модуля будет файл (обычно называемый BMI, «интерфейс двоичного модуля»), который компилятор может быстро прочитать и преобразовать в свои внутренние структуры данных. Более того, если вы компилируете несколько блоков перевода в одном и том же процесс компиляции, тогда они могут делиться загруженными модулями. В конце концов, GLM не меняется в зависимости от того, откуда вы его импортируете, поэтому нет причин даже перезагружать модуль, вы просто используете то, что уже находится в памяти.

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

    Предположим, что ваш GLFWin -воздушный модуль и модуль, который его потребляет, в какой-то момент используют std::vector. Допустим, вы изменили GLM, поэтому вам нужно перекомпилировать оба модуля. В мире заголовков этот также означает, что оба файла должны перекомпилировать заголовок <vector>, даже если он не изменился и вообще не зависит от GLM. Вот как работает включение текста.

    В модульном мире им не нужно перекомпилировать модуль vector. Он никак не зависит от модуля GLM, поэтому он может просто использовать уже существующий модуль vector. И это верно для любых включенных модулей, которые не зависят от GLM. Таким образом, хотя вам все еще нужен каскад перекомпиляций, сами перекомпиляции должны быть значительно быстрее, поскольку не нужно перекомпилировать все, что использует каждый модуль перевода. Файл из 5000 строк перекомпилируется как файл из 5000 строк, а не 5000+, сколько бы строк он не включал.

0 голосов
/ 11 марта 2019

Концепция модуля меняет наше представление о зависимостях. Больше не будет заголовков, кроме интерфейсов двоичных модулей (BMI), которые генерируются компилятором и содержат всю информацию о размере объекта, структурах объекта и зависимостях. Модуль вашего класса должен зависеть от модуля GLFWindow и glm :: mat, так как иначе вы не сможете его скомпилировать. Таким образом, в каком-то смысле вам все еще нужно представить свои внутренние данные другим классам, но вашему компилятору не нужно обходить все включения, а только импорт импортов BMI, которые необходимы для понимания интерфейсов классов / функций и, если он находит несколько раз один и тот же ИМТ в качестве зависимости он будет анализировать только один раз.

Это также означает, что вы больше не будете разделять определения и объявления в отдельных файлах, поскольку это не имеет никакого смысла. В итоге вы получите нечто, похожее на файл Java .class.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...