首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++20模块“循环依赖”

C++20模块“循环依赖”
EN

Stack Overflow用户
提问于 2021-07-07 16:13:44
回答 3查看 736关注 0票数 2

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

“无法构建以下源文件,因为它们之间存在循环依赖关系: Module1.ixx依赖于Module2.ixx依赖于Module1.ixx。”

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

我成功地尝试了C++17头和源文件(.h和.cpp)的代码

代码语言:javascript
复制
// 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;

代码语言:javascript
复制
// Class1.cpp
#include "Class1.h"
modClass1_ mc1;
modClass2_ modClass1_::mc2;

代码语言:javascript
复制
// Class2.h
#pragma once
#include "Class1.h"
class modClass2_
{
public:
    modClass2_() {};
    ~modClass2_() {};
    int V = 1;
    int getV() { return V; };
    int getClass1V();
};

代码语言:javascript
复制
// Class2.cpp
#include "Class2.h"
int modClass2_::getClass1V()
{
    return mc1.V;
}

代码语言:javascript
复制
// 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)尝试但失败的代码

代码语言:javascript
复制
// 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;

代码语言:javascript
复制
// 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 2019 x MSVC-2019 \ C++20 Windows 10 Pro

EN

回答 3

Stack Overflow用户

发布于 2021-07-07 16:57:42

与头文件一样,您可以将模块接口文件从模块实现文件中分离出来。示例:

模块1.ixx:

代码语言:javascript
复制
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:

代码语言:javascript
复制
export module Module2;

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

模块2.cpp:

代码语言:javascript
复制
import Module1;
import Module2;

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

main.cpp:

代码语言:javascript
复制
#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实现文件中,但实际上您很可能希望将更多的东西移出接口。

票数 4
EN

Stack Overflow用户

发布于 2021-12-09 12:49:06

我有一个树数据结构,分为两个模块,需要相互引用,以及posted an answer如何使其工作。复制它,下面是一个使用模板来打破循环依赖的绝望解决方案:

代码语言:javascript
复制
// A_impl.cc

export module A_impl;

export template <typename B> class A_impl {
    public:
        void f(B& b) {}
};
代码语言:javascript
复制
// B.cc

export module B;

import A_impl;

export class B;

typedef A_impl<B> A;

export class B {
    public:
        void f(A& a) {}
};
代码语言:javascript
复制
// A.cc

export module A;

export import A_impl;
import B;

export typedef A_impl<B> A;
代码语言:javascript
复制
// main.cc

import A;
import B;

int main(void) {
    A a;
    B b;

    a.f(b);
    b.f(a);

    return 0;
}

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

票数 0
EN

Stack Overflow用户

发布于 2022-05-16 04:27:51

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

代码语言:javascript
复制
// A.cc

export module Cyclic:A;

export class B;
export class A {
public:
    char name() { return 'A'; }
    void f(B& b);
};
代码语言:javascript
复制
// B.cc

export module Cyclic:B;

export class A;
export class B {
public:
    char name() { return 'B'; }
    void f(A& a);
};
代码语言:javascript
复制
// A_impl.cc

module Cyclic:A_impl;

import Cyclic:A;
import Cyclic:B;

import <iostream>;

void A::f(B& b) {
  std::cout << name() << " calling " << b.name() << std::endl;
}
代码语言:javascript
复制
// B_impl.cc

module Cyclic:B_impl;

import Cyclic:B;
import Cyclic:A;

import <iostream>;

void B::f(A& a) {
  std::cout << name() << " calling " << a.name() << std::endl;
}
代码语言:javascript
复制
// Cyclic.cc

export module Cyclic;
export import :A;
export import :B;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68289586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档