Модули С++20
В стандарте C++20 модули представляют собой новый способ организации и использования кода, который пришел на смену традиционным включаемым заголовочным файлам. Модули предоставляют следующие преимущества:
- Ускорение сборки, благодаря предкомпиляции модулей.
- Изоляция зависимостей, т.е. исключает проблемы дублирования символов и упрощает инкапсуляцию.
- Четкая структура, что улучшает читаемость и поддержку кода.
Особенности работы с модулями
- Ключевое слово export экспортирует элементы (функции, классы, переменные и т.д.) из модуля.
- Ключевое слово import используется для подключения модулей.
- Файлы .cppm и в VS 2022 .ixx рекомендуемое расширение для файлов модулей.
Модули в C++ делают код более структурированным и сокращают количество проблем, связанных с классическими заголовочными файлами, такими как множественные включения и долгие времена компиляции.
Для работы с модулями в Visual Studio 2022 установите настройки проекта как на картинке ниже.
Убедитесь, что Visual Studio поддерживает модули. Используйте последнюю версию Visual Studio (2022 или новее). Поддержка модулей появилась в Visual Studio начиная с версии 2019 (16.8), но она была экспериментальной и сильно улучшилась в 2022.
Проверьте, что у вас установлены необходимые компоненты:
- компилятор MSVC с поддержкой C++20.
Visual Studio требует корректной структуры и расширений файлов:
- файлы модулей должны иметь расширение .ixx
(например, vector.ixx
), а не .cppm
.
Пример кода
// модуль файл vector2d.ixx #include <iostream> export module vector2d; export class Vector2D { private: double x, y; // Координаты вектора public: // Конструкторы Vector2D() : x(0), y(0) {} Vector2D(double x, double y) : x(x), y(y) {} // Методы доступа double get_x() const { return x; } double get_y() const { return y; } void set_x(double value) { x = value; } void set_y(double value) { y = value; } // Методы работы с вектором double length() const { return std::sqrt(x * x + y * y); } Vector2D normalize() const { double len = length(); if (len == 0) { throw std::runtime_error("Cannot normalize a zero-length vector."); } return Vector2D(x / len, y / len); } // Операции над векторами Vector2D operator+(const Vector2D& other) const { return Vector2D(x + other.x, y + other.y); } Vector2D operator-(const Vector2D& other) const { return Vector2D(x - other.x, y - other.y); } double dot(const Vector2D& other) const { return x * other.x + y * other.y; } // Перегрузка вывода friend std::ostream& operator<<(std::ostream& os, const Vector2D& v) { os << "(" << v.x << ", " << v.y << ")"; return os; } };
Ключевое слово export
указывает, что содержимое этого модуля доступно для других файлов через import
.
// файл main.cpp который использует модуль vector2d.ixx import vector2d; // Импортируем модуль #include <iostream> int main() { try { // Создаём векторы Vector2D v1(3.0, 4.0); Vector2D v2(1.0, 2.0); // Выводим информацию о векторах std::cout << "Vector v1: " << v1 << "\n"; std::cout << "Vector v2: " << v2 << "\n"; // Выполняем операции Vector2D v3 = v1 + v2; Vector2D v4 = v1 - v2; std::cout << "v1 + v2: " << v3 << "\n"; std::cout << "v1 - v2: " << v4 << "\n"; std::cout << "Dot product of v1 and v2: " << v1.dot(v2) << "\n"; std::cout << "Length of v1: " << v1.length() << "\n"; Vector2D normalized = v1.normalize(); std::cout << "Normalized v1: " << normalized << "\n"; } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << "\n"; } return 0; }