Простые приложения на С++
December 25, 2024

Модули С++20

В стандарте C++20 модули представляют собой новый способ организации и использования кода, который пришел на смену традиционным включаемым заголовочным файлам. Модули предоставляют следующие преимущества:

  1. Ускорение сборки, благодаря предкомпиляции модулей.
  2. Изоляция зависимостей, т.е. исключает проблемы дублирования символов и упрощает инкапсуляцию.
  3. Четкая структура, что улучшает читаемость и поддержку кода.

Особенности работы с модулями

  • Ключевое слово export экспортирует элементы (функции, классы, переменные и т.д.) из модуля.
  • Ключевое слово import используется для подключения модулей.
  • Файлы .cppm и в VS 2022 .ixx рекомендуемое расширение для файлов модулей.

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

Для работы с модулями в Visual Studio 2022 установите настройки проекта как на картинке ниже.

Убедитесь, что Visual Studio поддерживает модули. Используйте последнюю версию Visual Studio (2022 или новее). Поддержка модулей появилась в Visual Studio начиная с версии 2019 (16.8), но она была экспериментальной и сильно улучшилась в 2022.

Проверьте, что у вас установлены необходимые компоненты:

- C++ модульная поддержка.

- компилятор 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;
}

import vector2d подключает модуль vector2d.

Телеграмм