10

我最近一直在试验 MSVC 提供的模块实现,我遇到了一个有趣的场景。我有两个类在它们的接口中相互依赖,这意味着我必须使用前向声明来编译它。以下代码显示了一个示例:

Module interface

export module FooBar;

export namespace FooBar {
    class Bar;

    class Foo {
    public:
        Bar createBar();
    };

    class Bar {
    public:
        Foo createFoo();
    };
}

Module implementation

module FooBar;

namespace FooBar {
    Bar Foo::createBar() {
        return Bar();
    }

    Foo Bar::createFoo() {
        return Foo();
    }
}

现在我想将这两个类拆分为它们自己的名为Foo和的模块Bar。但是,每个模块都需要导入另一个,因为它们的接口相互依赖。根据目前的模块提案,不允许循环接口导入。本文建议使用proclaimed ownership声明,但似乎尚未在模块的 MSVC 实现中实现。

因此,我是否正确假设目前无法使用 MSVC 提供的当前实现来解决这种情况?还是有一些我想念的替代品?在这种情况下,情况非常简单,但是我在模块化具有许多具有此类依赖关系的类的库时遇到了这个问题。我意识到循环依赖通常表明设计不好,但是在某些情况下,它们是不可避免的或难以重构的。

4

1 回答 1

2

您可以创建第三个模块,该模块仅将前向声明导出到您的每个类(可能是许多类)。
然后将此模块导入到您的两个(或所有)模块中,它提供实现每个模块所需的前向声明。

不幸的是,MSVC 仍然(今天是 16.7 版)模块存在问题。尽管这种方法有效,但您经常会收到完全疯狂的错误消息;例如,“无法将 MyClass* 转换为 MyClass* - 未提供转换(此示例发生在您直接将同一个类的前向声明添加到多个模块中;编译器认为它们是不同的动物)。
另一个问题是如果您忘记导入所有需要的模块,错误消息要么严重误导(“该类中没有这样的方法”),要么编译器因内部错误而中止。

在他们完成工作之前不要期望太多。

于 2020-08-10T05:36:10.433 回答