https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98885
--- Comment #7 from Nathan Sidwell <nathan at gcc dot gnu.org> --- My mistake. interface and implementation partitions do not follow the non-partition behaviour. You have two M:A partitions (one an interface and one an implementation). This is what you want: A.cc: export module M:A; export class B; export class A { void f(B const &) const; }; B.cc: export module M:B; export class A; export class B { void f(A const &) const; }; M.cc: export module M; export import :A; export import :B; M-impl.cc: module M; void A::f(B const &) const {} void B::f(A const &) const {} devvm1702:10>./cc1plus -fmodules-ts -quiet A.cc devvm1702:11>./cc1plus -fmodules-ts -quiet B.cc devvm1702:12>./cc1plus -fmodules-ts -quiet M.cc devvm1702:13>./cc1plus -fmodules-ts -quiet M-impl.cc you could of course split M-impl.cc into two if you want, one for the A bits and one for the B bits