c++ - #include 模板递归

标签 c++ templates cmake linker-errors

我有这样的问题Why can templates only be implemented in the header file? (还有 Correct way of structuring CMake based project with Template class )但包含递归。

代码:

啊啊

#pragma once
#include "B.h"

struct A
{
    B b;
    void doThingA() {}
};

B.h

#pragma once
struct A;

struct B
{
    A *a;
    template<typename T>
    void doThingB();
};

#include "A.h"

template<typename T>
void B::doThingB()
{
    a->doThingA();
}

主要.cpp

#include "A.h"

int main() {}

错误:

In file included from A.h:2,
                 from main.cpp:1:
B.h: In member function 'void B::doThingB()':
B.h:16:6: warning: invalid use of incomplete type 'struct A'
   16 |     a->doThingA();
      |      ^~
B.h:2:8: note: forward declaration of 'struct A'
    2 | struct A;
      |        ^

B.h 包含来自 A.hB.h 中模板函数实现所需的 A.h 不包含。由于模板的原因,我也无法对 .cpp 实现。

可以通过使用模板的显式实例化来解决,但我想知道另一种解决方案。

最佳答案

当您拥有紧密耦合的类型时,最简单的解决方案是将它们放在单个头文件中。

#pragma once

// forward declaration of A
struct A;

// declare B, since A needs it
struct B
{
    A *a;
    template<typename T>
    void doThingB();
};

// now we can declare A
struct A
{
    B b;
    void doThingA() {}
};

// and finally, implement the parts of B that need A
// and need to be in the header
template<typename T>
void B::doThingB()
{
    a->doThingA();
}

如果你还想要一个B.h,那么它可以是一行:

#include "A.h"

如果您想将 A/B 拆分为您自己的组织的多个 header ,一个简单的解决方案是添加编译时检查以确保文件不是直接包含在内。

// A.h
#pragma once

#define A_IMPL

#include "B_impl.h"

#undef A_IMPL
// B.h
#pragma once

#ifndef A_IMPL

#error "B_impl.h can't be included directly; use A.h"

#endif

struct A;

struct B
{
    A *a;
    template<typename T>
    void doThingB();
};

#include "A_impl.h"

template<typename T>
void B::doThingB()
{
    a->doThingA();
}
// A_impl.h
#pragma once

#ifndef A_IMPL

#error "A_impl.h can't be included directly; use A.h"

#endif

struct A
{
    B b;
    void doThingA() {}
};

如果您希望更多的 header 直接使用 impl 文件,您可以使 #ifdef 检查更复杂,但公共(public)接口(interface)仍然幸福地不知道。

关于c++ - #include 模板递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71119125/

相关文章:

c++ - 如何在 C++ 中将结构初始化为 0

c++ - 用户定义的重载运算符 * 与 std::chrono::duration

c++ - iPhone编译移植代码问题: sub class of template parameter base class inaccessible

c++ - 嵌套概念多态模板

linux - CMake 在 Ubuntu 上的错误路径中寻找 Qt 库

c++ - 带有 CMake 和静态库/Z7 标志的 Visual Studio

cmake - 如何为库编写 CMake 安装?

c++ - 在 win2k3 上运行 .exe 时出现 "The procedure entry point GetErrorMode could not be located in the dynamic link library kernel32.dll"错误

c++ - 类内枚举

c++ - 需要帮助理解 "rand() % 67 < 10"