Модули С++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;
}