Re-exporting Modules (Turkish Van)
A Partitioned Module (Javanese) used export import :Balinese; to re-export a partition of the same module. The export import syntax isn’t limited to partitions, though — a module can just as well re-export an entirely separate, unrelated top-level module. This chapter builds a small umbrella module that does exactly that, composing two independent modules into a single consumer-facing import.
Module TurkishAngora
A small, self-contained module, unaware it will later be re-exported.
1 module;
2
3 #include <print>
4
5 export module TurkishAngora;
6
7 export auto angora_meow() -> void {
8 std::println("Ankara kedisi «Miyav» der.");
9 }
Module TurkishVan
1 module;
2
3 #include <print>
4
5 export module TurkishVan;
6
7 export import TurkishAngora; // umbrella re-export: importing TurkishVan
8 // transitively brings in TurkishAngora's
9 // exports too, composing two independent
10 // top-level modules into one consumer import.
11 // Contrast with Javanese's `export import
12 // :Balinese;`, which re-exports a partition
13 // of itself rather than a separate module.
14
15 export auto van_meow() -> void {
16 std::println("Van kedisi «Miyav» der.");
17 }
The only new syntax here is on line 7: export import TurkishAngora; names a complete, independent module rather than a :partition. Everything TurkishAngora exports becomes visible to anyone who imports TurkishVan, without them ever writing import TurkishAngora; themselves.
User Code: main.cpp
1 import TurkishVan; // the only import needed -- angora_meow() comes along
2 // via TurkishVan's umbrella re-export
3
4 auto main() -> int {
5 van_meow();
6 angora_meow();
7
8 return 0;
9 }
main.cpp imports only TurkishVan (line 1) and calls both van_meow(), native to TurkishVan, and angora_meow(), which arrived transitively. There is no import TurkishAngora; anywhere in this file.
![]() |
Re-exporting two modules that happen to export the same name is a compile error, not a silent shadowing — an umbrella module can’t resolve which one you meant. This is worth checking for before composing modules you didn’t write yourself. |
Building With CMake
TurkishAngora and TurkishVan are separate library targets; TurkishVan links TurkishAngora PUBLIC so both its own compilation and any importer’s compilation can see it.
1 cmake_minimum_required(VERSION 3.30.5)
2
3 project(TurkishVan LANGUAGES CXX)
4
5 add_library(turkish_angora)
6 target_compile_features(turkish_angora PUBLIC cxx_std_23)
7 target_sources(turkish_angora
8 PUBLIC
9 FILE_SET cxx_modules TYPE CXX_MODULES
10 FILES TurkishAngora.cppm
11 )
12
13 add_library(turkish_van)
14 target_compile_features(turkish_van PUBLIC cxx_std_23)
15 target_sources(turkish_van
16 PUBLIC
17 FILE_SET cxx_modules TYPE CXX_MODULES
18 FILES TurkishVan.cppm
19 )
20 # turkish_van's own scan needs to see TurkishAngora's BMI, and importers of
21 # turkish_van need to transitively link turkish_angora too -- PUBLIC covers
22 # both.
23 target_link_libraries(turkish_van PUBLIC turkish_angora)
24
25 add_executable(${PROJECT_NAME} main.cpp)
26 target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
27
28 target_link_libraries(${PROJECT_NAME} turkish_van)
The PUBLIC on line 22’s target_link_libraries() is the important detail — a PRIVATE link would let turkish_van’s own sources see turkish_angora, but the executable target that only links turkish_van (line 27) wouldn’t transitively pick it up, and the final link would fail to find angora_meow()’s definition.
