16

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?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • You mislabeled your code as c/c++. Please label it as Typescript. – StarShine Oct 04 '17 at 10:28
  • 4
    @StarShine - What are you on about? – StoryTeller - Unslander Monica Oct 04 '17 at 10:44
  • module, import and syntax such as A{}.doA() are, to my knowledge, not valid c++. – StarShine Oct 04 '17 at 12:35
  • 5
    @StarShine - Then I suggest you update your knowledge. – StoryTeller - Unslander Monica Oct 04 '17 at 12:37
  • 2
    @StoryTeller ok, apologies, as this is new to me. From http://en.cppreference.com/w/cpp/experimental I learn that this is still experimental and draft stage. Cppreference.org has the keywords listed, but there's no content behind the links yet. – StarShine Oct 04 '17 at 12:45
  • @GuillaumeRacicot I dig the humor, you're right about the tags ;) Thanks for sharing, you triggered my curiosity! Any good resources apart from the draft docs? – StarShine Oct 04 '17 at 12:46
  • 2
    @StarShine - There are the CppCon talks. [Here's the one from 2015](https://www.youtube.com/watch?v=RwdQA0pGWa4). That's more introductory, but is probably different than the current state of the proposal. They originally aimed to add it into C++17. – StoryTeller - Unslander Monica Oct 04 '17 at 13:07
  • @StarShine glad to hear! Here's a [guide written by the build2 developer](https://build2.org/build2/doc/build2-build-system-manual.xhtml#cxx-modules-intro). He also written [module design guidelines](https://build2.org/build2/doc/build2-build-system-manual.xhtml#cxx-modules-guidelines). – Guillaume Racicot Oct 04 '17 at 20:05
  • @GuillaumeRacicot - Seeing as the bounty period ends tomorrow, how to you feel about the posted answer? – StoryTeller - Unslander Monica Oct 10 '17 at 06:52
  • @StoryTeller it could benefit of more explanation, but serves it's purpose. It could have quote the content of the PDTS to pinpoint the rule that forbid it, and I would gladly give him the points. – Guillaume Racicot Oct 10 '17 at 13:52

2 Answers2

2

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.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • So the interface is the whole file, not just the exported stuff. Interesting. I guess this is because the whole interface unit must be compiled in order to produce an interface binary file. – Guillaume Racicot Oct 10 '17 at 18:46
  • @GuillaumeRacicot: No, the _interface_ is just the exported items (\[dcl.module.interface]/1). However, it is the interface _unit_ that is restricted. – Davis Herring Oct 11 '17 at 00:39
  • @DavisHerring ah yes, this is what I meant. I'm still not used with all those new terms! – Guillaume Racicot Oct 11 '17 at 00:41
1

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".

Davis Herring
  • 36,443
  • 4
  • 48
  • 76