So far it seems to me that including almost any libstdc++ header in a C++ module interface causes compile errors on clang 14.0.0 and the libstdc++ that comes bundled with GCC 11.2.0. I wonder if I am doing something wrong or if this is just not something that is supported yet. (I see that the Clang modules support is "partial", but haven't been able to find what is implemented and what is not.)
Here's a trivial module example that I got to work with clang-14 in Linux, linked with libstdc++. It demonstrates that libstdc++ headers can be used in a module implementation, but this example does not #include anything in the module interface:
// mod_if.cc
export module mod;
export int foo();
// mod.cc
module;
#include <iostream>
module mod;
int foo() {
std::cout << "Hello world from foo()" << std::endl;
return 42;
}
// use.cc
import mod;
#include <iostream>
int main() {
std::cout << foo() << std::endl;
}
This works:
$ CXXFLAGS="-std=c++20 -fmodules -fprebuilt-module-path=prebuilt"
$ clang++ -c $CXXFLAGS -Xclang -emit-module-interface -o prebuilt/mod.pcm mod_if.cc
$ clang++ -c $CXXFLAGS -fmodule-file=prebuilt/mod.pcm mod.cc -o mod.o
$ clang++ $CXXFLAGS use.cc mod.o prebuilt/mod.pcm -o use
$ ./use
Hello world from foo()
42
However, suppose I wanted foo
to return a std::string
:
// mod_if.cc
module;
#include <string>
export module mod;
export std::string foo();
// mod.cc
module;
#include <string>
module mod;
std::string foo() {
return "42";
}
// no use.cc needed since the error happens when building mod.cc
This does not compile (first of many similar errors shown):
$ clang++ -c $CXXFLAGS -Xclang -emit-module-interface -o prebuilt/mod.pcm mod_if.cc
$ clang++ -c $CXXFLAGS -fmodule-file=prebuilt/mod.pcm mod.cc -o mod.o
In file included from mod.cc:2:
In file included from /usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/string:40:
In file included from /usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/char_traits.h:39:
In file included from /usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/stl_algobase.h:64:
In file included from /usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/stl_pair.h:65:
/usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/compare:348:33: error: redefinition of '__cmp_cat_id<std::partial_ordering>'
inline constexpr unsigned __cmp_cat_id<partial_ordering> = 2;
^
/usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/stl_pair.h:65:11: note: '/usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/compare' included multiple times, additional include site in header from module 'mod.<global>'
# include <compare>
^
/usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/stl_pair.h:65:11: note: '/usr/lib64/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../include/c++/11.2.0/compare' included multiple times, additional include site in header from module '<global>'
# include <compare>
^
mod.cc:1:1: note: <global> defined here
module;
^
Is there currently a way to make this code work (without resorting to writing module maps for the libstdc++ headers)? Why does this error happen? It sounds strange that the inline constexpr
declaration included in the global module fragment gets exported, but then I don't claim to understand modules well.