Peter Kraus
Peter Kraus

Reputation: 79

C++ modules: compiler reports multiple definition

I'm in the process of migrating a C++ graphics application from header files to modules. A problem with circular dependencies (C++ modules and circular class reference) has been resolved initially. But now I'm stuck in a slightly more complicated situation. I have a module with three partitions: Part1, PartBase and PartDerived. Two of the participants (PartBase and Part1) have a mutual dependency, which is resolved by means of a forward declaration. In addition, PartBase and PartDerived have an inheritance relationship. The real situation is of course more complex, but this is a stripped down configuration, where I can reproduce the issue.

export module Module:Part1;

// :import PartBase would create circular dependency 
class PartBase;  // forward declaration is ok

export class Part1
{
    PartBase * pBase;
};


export module Module:PartBase;

import :Part1;

export class PartBase
{
    Part1 * pPart1;
};


export module Module:PartDerived;

import :PartBase;

export class PartDerived : public PartBase {};


export module Module;

export import :Part1;
export import :PartBase;
export import :PartDerived;

The module compiles without any problems. However, when a refer to classes defined in the module from an outside client module

import Module;

export class Client
{
    PartDerived* pDerived;
    PartBase* pPartBase;
};

the compiler reports an error in the line, where PartBase is used:

"unrecoverable error importing module 'Module': symbol 'PartBase' has already been defined"

I use Microsoft Visual Studio Community 2022 (64-bit) - Version 17.3.3.

I can't explain this message and suspect it's a compiler error. But I've learned that it's better to look for your own mistakes before blaming the tools. Does anyone have an idea?

Upvotes: 5

Views: 322

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41760

Seems like a compiler bug, but it's really hard to validate since all compilers have bugs with modules.

With the current compilers, it worked for me to export the forward declaration in :Part1:

export class PartBase;  // forward declaration is ok

export class Part1
{
    PartBase * pBase;
};

Live example

Upvotes: 1

Related Questions