Home > Software engineering >  Forward declarations and incomplete types in C modules
Forward declarations and incomplete types in C modules

Time:05-30

I have been experimenting with C 20 modules, and there seems to be something different with the usual hpp/cpp approach. The following doesn't compile (I'm using the latest preview of MSVC).

foo.ixx

export module foo;

import std.memory;

export
struct Bar;

export
struct Foo {
  std::unique_ptr<Bar> ptr;
};

bar.ixx

export module bar;

import std.core;

import foo;

struct Bar {
  void func(Foo& f) {}
};

main.cpp

import foo;
import bar;

int main() {
  Foo f;
}

My questions:

  1. Is there a better way to resolve this other than putting Foo and Bar into one file?
  2. Does this imply that template instantiation is done before module "linking"?

CodePudding user response:

Modules own the declarations placed into them. And if a module owns a declaration, all other declarations must also be part of the same module.

Bar was declared to be in foo. Therefore, any other declarations of it (and a definition is a declaration) must also be within foo.

They don't have to be in the same file, but they do have to be in the same module. If you want the definition of Bar to be accessible by users of the module foo, you should use a module interface unit partition:

export module foo:BarDef;

import std.core;

export struct Bar {
  void func(Foo& f) {}
};

And the module's primary interface unit must import this partition:

export module foo;

import std.memory;

export struct Bar;

export struct Foo {
  std::unique_ptr<Bar> ptr;
};

export import :BarDef;

MSVC's naming convention for module files says that .ixx should be used for any interface units, so both of these files should be .ixx files.

  • Related