I was reading about modules, and I wished to do something like this:
a.cpp
module foo.a;
export namespace foo {
struct A {
void doA();
};
}
import foo.b;
void foo::A::doA() {
B{}.doB();
}
b.cpp
module foo.b;
export namespace foo {
struct B {
void doB();
void start();
};
}
import foo.a;
import std.io;
void foo::B::doB() {
std::cout << "Stuff done!" << std::endl;
}
void foo::B::start() {
A{}.doA();
}
main.cpp
import foo.b;
int main() {
foo::B{}.start();
}
Since module interfaces cannot use each other, for that to work, everything after the exported namespace must not be part of the interface. Is the above correct according to the current TS? For circular dependency in the implementation, is it required to split it into another file?
The export as namespace form creates a global variable so it can be used without importing, but you may still import it with the import { name } from "some-library" form of import.
You can export an entire C++ class by placing the __declspec(dllexport) before the class name, or you can export a single method by placing __declspec(dllexport) before the method name. Make class methods static and public. The C/C++ DLL Adapter does not allow you to call public non-static methods.
From the Working Draft, Extensions to C++ for Modules (found in Experimental C++ Features), page 13, §10.7.2:3:
A module
M1
has an interface dependency on a moduleM2
if the module interface ofM1
contains a module-import-declaration nominatingM2
. A module shall not have a transitive interface dependency on itself.
Example:
// Interface unit of M1
export module M1;
import M2;
export struct A { };
// Interface unit of M2
export module M2;
import M3;
// Interface unit of M3
export module M3;
import M1; // error: cyclic interface dependency M3 -> M1 -> M2 -> M3
Q: "For circular dependency in the implementation, is it required to split it into another file?"
A: Yes.
Q: "Is the above correct according to the current TS?"
A: No.
In your code, you have an error, since foo.a
and foo.b
form a cyclic interface dependency.
Yes, you have to use a separate implementation file for at least one of the modules (the one that is conceptually "lower-level"). The PDTS's [dcl.module.import]/3 says
A module
M1
has an interface dependency on a moduleM2
if the module interface ofM1
contains a module-import-declaration nominatingM2
. A module shall not have a transitive interface dependency on itself.
This applies regardless of the location of the module-import-declaration, since export
can appear anywhere and multiple times in a module interface unit. The rule is meant to prevent the appearance of types and templates from each of two modules in the interface of the other, since then neither could be imported "first".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With