C ++模块(MSVC)中的转发声明

时间:2018-07-16 13:08:25

标签: c++ visual-c++ circular-dependency c++-modules

我最近一直在尝试由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();
    }
}

现在,我想将这两个类拆分为名为FooBar的自己的模块。但是,每个模块都需要导入其他模块,因为它们的接口相互依赖。根据目前的the modules proposal,不允许导入圆形接口。 This article建议使用proclaimed ownership声明,但似乎尚未在模块的MSVC实现中实现。

因此,我是否正确假设当前无法使用MSVC提供的当前实现解决这种情况?还是我缺少其他选择?在这种情况下,情况非常琐碎,但是我在模块化具有许多具有此类依赖关系的类的库时遇到了此问题。我意识到循环依赖通常是不良设计的迹象,但是在某些情况下,它们是不可避免的或难以重构的。

1 个答案:

答案 0 :(得分:1)

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

不幸的是,MSVC仍然存在模块问题(今天是16.7版)。尽管这种方法行得通,但您经常会收到完全错误的错误消息;例如,“无法将MyClass *转换为MyClass *-不提供转换(此示例发生在您将对同一个类的前期标签直接添加到多个模块中时;编译器将它们视为不同的动物)。
另一个问题是,如果您忘记导入所需的所有模块,则错误消息可能会引起严重误导(“该类中没有此类方法”),或者编译器因内部错误而中止。

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