innochenti
innochenti

Reputation: 1103

Submodules: how to divide C++ module into submodules

I have a simple project with one module.

Units.ixx

module;

#include <cassert>
export module Units;
export class Base {
public:
};
export void foo();

Units_impl.ixx

export module Units;

class Derived : public Base {  // 'Base': base class undefined
};

export void foo() {
    Derived derived;
}

Main.cpp

import Units;

int main() {
    return foo();
}

Compiler shows me an error 'Base': base class undefined. Is it expected behavior? If yes, how to divide modules into submodules? I’d like to have Derived inside my Units module but in a different file.

Upvotes: 4

Views: 3996

Answers (2)

bitnick
bitnick

Reputation: 2073

Module.ixx

export module mybar;

export import :Wheel;
export import :Bus;

Wheel.ixx

export module mybar:Wheel;

export 
class Wheel{
};

Bus.ixx

export module mybar:Bus;
import :Wheel;

export 
class Bus :public Wheel {
};

Upvotes: 3

ThirdWiseMonkey
ThirdWiseMonkey

Reputation: 239

To split a module into multiple files you need to use partitions. To do this you need to first create a primary interface:

export module Units;

then you declare each separate file that makes up the module as a named partition(export module <module_name>:<partition_name>) eg:

export module Units:Impl;

This does not by itself share classes, variables or functions between the files though. To access a partition from the primary interface or another partition you need to add an import statement import :<partition_name> eg:

import :Impl;

so in the code you have above Units_impl.ixx knows nothing about Base as it is declared in a separate file hence the error.

This also means you cannot declare the class Base in the primary interface if you want to have access to it from a partition as this would result in a cyclic dependancy. Ie the partition would need to import Units(the primary interface) which would itself need to import the partition(Units:Impl). So at the very least your files would need to look something like:

Units.ixx:

export module Units;
import :Impl;

export void foo();

Units_Impl.ixx:

class Base{};
class Derived: public Base{};

export void foo()
{
    Derived derived;
}

Main.cpp:

import Units;

int main()
{
    foo();
    return 0;
}

If you didn't want Base to be in the same file as Derived you'd need to create another partition in a separate file eg:

Units_Base.ixx:

export Units:Base;
export class Base{};

and then your Units_Impl.ixx would look like this:

export Units:Impl;
import :Base;

class Derived: public Base{};

export void foo()
{
    Derived derived;
}

Finally you can re-export from an imported module using export import <module_or_partition_name> eg:

export import :Impl;

this would then make export void foo(); in Units.ixx unnecessary and it would look like this:

export module Units;
export import :Impl;

Upvotes: 2

Related Questions