2015-09-06 3 views
1

Я знаю, как решить базовый пример циклической зависимости, с двумя классами, где каждый должен знать, что другой существует.
Тем не менее, я сейчас в ситуации, где пример более сложный, и форвардная декларация не является чем-то, что может исправить эту проблему.C++ Циркуляр #include, где форвардное объявление не является фиксированным

Рассмотрим эти три файла

// 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 my_thread.hpp for some reason. I don't know how it knows about thread_manager`.

+0

то почему вы помещаете определение 'somefunction', прежде чем объявлять' thread_manager'? –

+0

@PiotrSkotnicki Это циклическая зависимость, оба файла требуют друг друга как включить. И 'my_thread :: somefunction()' является шаблоном и должен быть в заголовке. – Zereges

+0

поместите их в один заголовок, затем (вместе с необходимыми определениями) –

ответ

1

Одним из путей решения этого было бы вводить менеджер потоков в качестве параметра шаблона:

// 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 должен пройти менеджер потоков в, но ничего не знаю о менеджере потоков не знает, так что вам должны впрыскивать менеджер потоков в some_class тоже:

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

Наконец, менеджер нить находится в положении, чтобы впрыснуть в себя 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, но ничего не делает, и установите этот класс в качестве параметра шаблона по умолчанию.

+0

Я отредактировал свой вопрос, пожалуйста, взгляните на него. – Zereges

+0

Впрыск зависимости будет распространяться до класса самого высокого уровня, поэтому вам придется вводить 'thread_manager' в' some_class'.Дайте мне секунду –

+0

Было бы неплохо, если бы я мог просто переслать объявление 'thread_manager :: static_function', не делая целых' # include' – Zereges

0
#include <list> 

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

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

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

Другой вариант: оставить декларацию SomeFunction в шаблоне и реализовать его в виде отдельного файла.

+1

AFAIK, определения функций шаблона должны быть в том же (заголовочном) файле, что и в классе hte определено. – Zereges

+0

_ "... и реализовать его в отдельном файле. _ [Нет!] (Http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header -файл) –

Смежные вопросы