Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is everything after an exporting namespace not exported?

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?

like image 709
Guillaume Racicot Avatar asked Sep 28 '17 13:09

Guillaume Racicot


People also ask

What is export as namespace?

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.

How do I export in C++?

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.


2 Answers

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 module M2 if the module interface of M1 contains a module-import-declaration nominating M2. 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.

like image 58
gsamaras Avatar answered Oct 20 '22 05:10

gsamaras


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 module M2 if the module interface of M1 contains a module-import-declaration nominating M2. 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".

like image 37
Davis Herring Avatar answered Oct 20 '22 05:10

Davis Herring