C++ Circular #include 前向声明未修复

标签 c++ c++11 include circular-dependency

我知道如何解决基本的循环依赖示例,有两个类,每个类都需要知道另一个存在。
但是,我现在的情况是,示例更复杂,前向声明不是可以解决该问题的东西。

考虑这三个文件

// my_thread.hpp
template<typename Function> class my_thread;

template<typename Return, typename... Input>
struct my_thread<Return(Input...)>
{
    void somefunction() { thread_manager::static_function(); }
}

// thread_manager.hpp
struct thread_manager
{
    static void static_function() { }
    std::list<some_class::thread_type> threads;
}

// some_class.hpp
struct some_class
{
    using thread_type = my_thread<int(some_class*)>
}

现在,显然 my_thread.hpp需要整个 thread_manager (或者至少它的功能?)。 thread_manager需要 using来自 some_class 的指令和 some_class依赖于 my_thread .由于 STL 容器需要完整的类型模板参数,我无法转发声明 my_thread .我什至无法给出 my_thread<T>::somefunction() 的定义,因为它是模板函数,需要放在标题中。
我的问题是,如何解决这种循环依赖?

有趣的是,MSVC 不需要 #include "thread_manager" in我的线程.hpp for some reason. I don't know how it knows about thread_manager`。

最佳答案

解决这个问题的一种方法是将线程管理器作为模板参数注入(inject):

// my_thread.hpp
template<typename ThreadManager, typename Function> class my_thread;

template<typename ThreadManager, typename Return, typename... Input>
struct my_thread<ThreadManager, Return(Input...)>
{
    void somefunction() { ThreadManager::static_function(); }
}

你的 some_class 必须传入线程管理器,但它对线程管理器一无所知,所以你也必须将线程管理器注入(inject)到 some_class 中:

// some_class.hpp
template<typename ThreadManager>
struct some_class
{
    using thread_type = my_thread<ThreadManager, int(some_class*)>;
};

最后,线程管理器可以将自己注入(inject)some_class:

// thread_manager.hpp
struct thread_manager
{
    static void static_function() { }
    std::list<my_thread<thread_manager, int(int)>> threads;
}

有了这个结构,就不再直接依赖于线程管理器了。

顺便说一句,您可能希望在某些单线程上下文中使用您的some_class。在这种情况下,您可以创建一个虚拟 ThreadManager,它提供与您的 thread_manager 相同的接口(interface)但不执行任何操作,并将此类设置为默认模板参数。

关于C++ Circular #include 前向声明未修复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32422171/

相关文章:

c++ - 返回 shared_ptr 时如何实现协变返回类型?

c++ - 在 C++11 中缺少 std::u8string

c++ - 如何在c++中直接使用addr2line

c++ - 将 lambda 转换为 std::tr1::function

C - 如何在没有 include 语句的情况下包含 c 源文件

c++ - G++ 错误 : In file included, 然后未声明 Foo

c++ - QSqlDatabasePrivate::removeDatabase: connection 'myConnectionName' is still in use, 所有查询将停止工作

c++ - 不使用虚函数的动机

c++ - 如何在模板参数中使用 std::is_pod?

javascript - 如何获取当前正在执行的javascript代码的文件路径