Módulos en C++20: el sistema de importación que reemplaza a los headers

Los archivos de cabecera (.h y .hpp) son el mecanismo de C++ para compartir declaraciones entre unidades de traducción. Funcionan pegando texto: el preprocesador copia el contenido del header en cada archivo que lo incluye. El resultado es que cada compilación re-analiza el mismo texto miles de veces, los macros se filtran entre unidades sin control y el orden de inclusión importa de formas inesperadas.

Los módulos de C++20 reemplazan ese mecanismo. En lugar de copiar texto, el compilador genera una representación binaria del módulo (un BMI, binary module interface) que se importa directamente. Sin preprocesador, sin macros filtradas, sin include guards.

Sintaxis básica

// matematica.cppm  (extensión habitual para módulos)
export module matematica;

#include <cmath>  // puedes incluir headers dentro de módulos

export double circunferencia(double radio) {
    return 2.0 * M_PI * radio;
}

export double area_circulo(double radio) {
    return M_PI * radio * radio;
}

// Esta función NO se exporta; es interna al módulo
double calcular_aux(double x) { return x * x; }
// main.cpp
import matematica;
import <print>;  // header unit (forma de importar headers clásicos)

int main() {
    std::println("Área: {:.2f}", area_circulo(5.0));
}

La función calcular_aux no es visible desde fuera del módulo aunque uses import matematica. Con los headers, cualquier cosa en el header es visible para todos.

export: qué es visible y qué no

Solo lo que lleva export es accesible desde fuera del módulo. Puedes exportar funciones, clases, enums, variables y namespaces:

export module mi_lib;

export namespace mi_lib {
    struct Punto { double x, y; };

    Punto sumar(Punto a, Punto b) {
        return { a.x + b.x, a.y + b.y };
    }
}

// Esto NO se exporta (sin export):
namespace detalle {
    void validar(Punto p) { /* ... */ }
}

Module partitions

Para módulos grandes, puedes dividirlos en particiones. Cada partición es un archivo separado pero pertenece al mismo módulo:

// geometria-figuras.cppm  (partición del módulo geometria)
export module geometria:figuras;

export struct Circulo { double radio; };
export struct Rectangulo { double ancho, alto; };
// geometria-calculos.cppm
export module geometria:calculos;
import :figuras;  // importa la partición del mismo módulo
import <cmath>;

export double area(Circulo c) { return M_PI * c.radio * c.radio; }
export double area(Rectangulo r) { return r.ancho * r.alto; }
// geometria.cppm  (interfaz principal del módulo)
export module geometria;
export import :figuras;   // re-exporta la partición
export import :calculos;
// main.cpp
import geometria;  // tiene todo: Circulo, Rectangulo, area()

import std: importar toda la librería estándar

C++23 añade la posibilidad de importar toda la librería estándar con una línea:

import std;  // C++23

int main() {
    std::println("{}", std::vector{1, 2, 3}.size());
}

Esto solo funciona si el compilador y la instalación de la stdlib lo soportan. GCC 15 y Clang 18+ con libc++ tienen soporte experimental. MSVC en VS2022 Update 4+ lo soporta bien.

Estado del soporte en compiladores (2026)

Esta es la parte que más afecta al uso práctico. El soporte de módulos ha avanzado pero aún tiene fricciones:

  • MSVC (VS2022): el soporte más maduro. Módulos básicos, particiones e import std funcionan bien.
  • GCC 14: soporte experimental. Los módulos básicos compilan, pero las particiones y header units tienen limitaciones. GCC 15 mejora bastante.
  • Clang 17/18: soporte experimental similar a GCC. Clang 20 avanza más.

CMake y módulos

CMake 3.28 añadió soporte experimental para módulos de C++20. La configuración mínima:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.28)
project(mi_proyecto CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)  # experimental

add_library(matematica)
target_sources(matematica
    PUBLIC
        FILE_SET CXX_MODULES FILES matematica.cppm
)

add_executable(app main.cpp)
target_link_libraries(app PRIVATE matematica)

La extensión .cppm es la convención más habitual pero no es obligatoria; CMake usa el FILE_SET CXX_MODULES para identificarlos.

¿Cuándo migrar a módulos?

Si tu proyecto es nuevo y usas MSVC, puedes explorar módulos ya. Si usas GCC o Clang, los módulos en proyectos de producción tienen más riesgo hasta que el soporte madure. El camino intermedio es usar módulos para código nuevo y mantener headers para las partes estables.

Los módulos no resuelven todos los problemas de tiempos de compilación (eso también depende de la arquitectura del código), pero en proyectos grandes con muchos includes repetidos la mejora es apreciable.

Esta característica conecta directamente con el artículo sobre CMake moderno en 2026, donde vemos cómo configurar el build system para sacarle partido. Y si te interesa qué más trae C++20 además de los módulos, el artículo sobre concepts y requires cubre otra de las grandes novedades del estándar.

Imagen: Pexels / Markus Winkler

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP