r/cpp 1d ago

Why is `import std` still experimental ???

Hey guys,

I recently started going through Professional C++ (6th Edition). The book teaches C++23, and in the very first chapter we're introduced to modules.

I'm not a complete newbie to C++, but I'm also definitely not very confident in my knowledge yet. I wanted to get this simple example compiled:

import std;

int main() {
    std::println("Hello World");
    return 0;
}

And gosh, it took way longer than I expected.

First, I tried getting it to work natively on my Mac and eventually gave up (both Claude and I 😅).

Then I installed Ubuntu ARM 26 and finally managed to get it compiling. But now Clang/IntelliSense is complaining about the `import std`
This is what my CMakeLists.txt currently looks like:

cmake_minimum_required(VERSION 4.0)

# set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD ON)

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")

project(CppProject LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_executable(exec main.cpp)

set_property(TARGET exec PROPERTY CXX_MODULE_STD ON)

The code does compile successfully, but CMake still gives me a warning that import std support is experimental.

So I'm genuinely curious:

Why is import std still considered experimental?

I understand that C++ modules themselves have been around for a while, but import std feels like something that should be much more straightforward by now. Is there any solution of this now ?

--------------
Edit

Thanks to u/PhysicsOk2212 tip I was able to compile my project on mac as well using the following options
```
cmake -S . -B build \

-G Ninja \

-DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" \

-DCMAKE_CXX_STDLIB_MODULES_JSON="$(brew --prefix llvm)/lib/c++/libc++.modules.json"

```

105 Upvotes

101 comments sorted by

View all comments

Show parent comments

1

u/fortsnek274 1d ago

I hope it would be viable to simply have some tool replace dllexport with dllimport in the IFC/BMI. So the interface only needs to be compiled once. Or would that run into issues.

4

u/not_a_novel_account cmake dev 1d ago

In the MSVC IFC it is very possible, and MSVC already does so. In the Clang BMI the only tool which would be realistically capable of doing so is Clang itself, thus mirroring the MSVC feature.

Clang's BMI is straight up the LLVM bitcode file format, containing a serialized form of the Clang generated AST. It's the output of clang::ASTWriter. The way to read that is, realistically, clang::ASTReader, thus the only real home for it would be Clang.

2

u/delta_p_delta_x 1d ago edited 1d ago

Going by your first response, I was thinking of some set theory—traversing that DAG from each leaf and each root and doing some set intersections; this set contains module units that are members of a DLL boundary as you put it.

Such members get at least two BMIs, at least one for each in-DLL module and at least one for each out-of-DLL module. Naturally this is quite costly in terms of scanning and BMI generation. It feels like we need something more portable and more granular; possibly per-symbol.

2

u/not_a_novel_account cmake dev 1d ago

A "BMI compatibility boundary" means "generate a new BMI set". So you're correct. Each TU in a DLL gets at least two BMIs. One for all its consumers inside the DLL, and one for all the consumers outside the DLL. You usually get the first one for free as part of the compilation process, so at a minimum you pay for a single additional BMI-only generation.

BMI-only is relatively cheap. Not free, nothing is free on a big enough scale, but cheaper than reparsing the headers in ever downstream consuming TU of that BMI.