C++20 模块"循环依赖"



我试图在另一个模块中包含模块,但由于以下错误而无法编译:

"无法构建以下源文件,因为它们之间存在循环依赖关系:模块 1.ixx 依赖于模块 2.ixx 依赖于模块 1.ixx。">

我想modClass1_包含modClass2_类,modClass2_包含指向静态modClass1_的指针。


Code 我尝试了 C++17 标头和源文件(.h 和 .cpp)成功尝试

// Class1.h
#pragma once
#include "Class2.h"
class modClass2_;
class modClass1_
{
public:
modClass1_() {};
~modClass1_() {};
int V = 2;
int getV() { return V; };
static modClass2_ mc2;
};
extern modClass1_ mc1;
// Class1.cpp
#include "Class1.h"
modClass1_ mc1;
modClass2_ modClass1_::mc2;
// Class2.h
#pragma once
#include "Class1.h"
class modClass2_
{
public:
modClass2_() {};
~modClass2_() {};
int V = 1;
int getV() { return V; };
int getClass1V();
};
// Class2.cpp
#include "Class2.h"
int modClass2_::getClass1V()
{
return mc1.V;
}
// Main.cpp
#include "Class1.h"
#include <iostream>
int main()
{
std::cout << mc1.getV() << "n"; // gets modClass1_ V directly
std::cout << mc1.mc2.getClass1V() << "n"; // gets modClass1_ V through modClass2_ through modClass1_
std::cout << mc1.mc2.getV() << "n"; // gets modClass2_ V through modClass1_
}

代码我尝试过但失败了 C++20 模块 (.ixx)

// Module1.ixx
export module Module1;
import Module2;
export class modClass1_
{
public:
modClass1_() {};
~modClass1_() {};
int getV() { return V; };
modClass2_ mc2;
int getModule2V() { return mc2.V; };
int V = 1;
};
export modClass1_ mc1;
// Module2.ixx
export module Module2;
import Module1;
export class modClass2_
{
public:
modClass2_() {};
~modClass2_() {};
int getV() { return V; };
int getModule1V() { return mc1.V; };
int V = 2;
};

任何帮助/建议将不胜感激。

环境:Visual Studio 2019 |MSVC-2019 |C++20 |视窗 10 专业版

就像头文件一样,您可以将模块接口文件与模块实现文件分开。例:

模块1.ixx:

export module Module1;
import Module2;
export class modClass1_
{
public:
modClass1_() {};
~modClass1_() {};
int getV() { return V; };
modClass2_ mc2;
int getModule2V() { return mc2.V; };
int V = 1;
};
export modClass1_ mc1;

模块2.ixx:

export module Module2;
export class modClass2_
{
public:
modClass2_() {};
~modClass2_() {};
int getV() { return V; };
int getModule1V();
int V = 2;
};

模块2.cpp:

import Module1;
import Module2;
int modClass2_::getModule1V()
{
return mc1.V;
}

主.cpp:

#include <iostream>
import Module1;
import Module2;
int main()
{
// NB: mc1 is a symbol imported from Module1
std::cout << "mc1.V: " << mc1.V << 'n';
std::cout << "mc1.getModule2V: " << mc1.getModule2V() << 'n';
modClass2_ mc2;
std::cout << "mc2.V: " << mc2.V << 'n';
std::cout << "mc2.getModule1V: " << mc2.getModule1V() << 'n';
}

请注意,modClass2_的接口不需要Module1的任何内容,因此Module2.ixx没有import Module1;Module2.cpp,实现所在的位置。

在我的示例中,我尽可能少地将Module2.ixx移动到Module2.cpp实现文件中,但实际上您可能希望将更多内容移出接口。

我有一个树形数据结构,分成两个需要相互引用的模块,并发布了如何使其工作的答案。复制粘贴它,这是一个通过使用模板打破循环依赖的绝望解决方案:

// A_impl.cc
export module A_impl;
export template <typename B> class A_impl {
public:
void f(B& b) {}
};
// B.cc
export module B;
import A_impl;
export class B;
typedef A_impl<B> A;
export class B {
public:
void f(A& a) {}
};
// A.cc
export module A;
export import A_impl;
import B;
export typedef A_impl<B> A;
// main.cc
import A;
import B;
int main(void) {
A a;
B b;
a.f(b);
b.f(a);
return 0;
}

目前 clang 不支持模块分区,因此使用该工具链,这似乎是在不同文件中定义 A 和 B 的唯一方法(没有#include),同时将它们放置在模块中。使用Visual Studio模块分区可能允许也可能不允许更干净的结构。

使用 gcc 测试,模块分区可以使用前向声明和内部模块链接来解决问题。注意:这不会将模块设置为相互依赖,整个循环依赖关系在单个模块中定义。

// A.cc
export module Cyclic:A;
export class B;
export class A {
public:
char name() { return 'A'; }
void f(B& b);
};
// B.cc
export module Cyclic:B;
export class A;
export class B {
public:
char name() { return 'B'; }
void f(A& a);
};
// A_impl.cc
import Cyclic:A;
import Cyclic:B;
import <iostream>;
void A::f(B& b) {
std::cout << name() << " calling " << b.name() << std::endl;
}
// B_impl.cc
import Cyclic:B;
import Cyclic:A;
import <iostream>;
void B::f(A& a) {
std::cout << name() << " calling " << a.name() << std::endl;
}
// Cyclic.cc
export module Cyclic;
export import :A;
export import :B;

相关内容

  • 没有找到相关文章

最新更新