Как избежать циклической зависимости с помощью шаблона - PullRequest
0 голосов
/ 01 июля 2018

Итак, я работаю в проекте системного API и пытаюсь выяснить, как избежать циклической зависимости в определении метода статического шаблона. Дело в том, что методы шаблона не могут быть определены в отдельном cpp, и я не могу определить его в заголовочном файле, потому что это может вызвать циклическую зависимость:

flow.h:

#include "system.h"
#include "flowImpl.h" //circular dependency
#include <vector>
#ifndef TRAB_INDIVIDUAL_FLOW_H
#define TRAB_INDIVIDUAL_FLOW_H

typedef std::vector<System*>::iterator SystemIterator;

class Flow {
public:

    //-----------------------------------
    //What's giving me problems
    template <typename T_FLOW_IMPL>
    static Flow* createFlow() {
        return FlowImpl::createFlow<T_FLOW_IMPL>();
    }

    template <typename T_FLOW_IMPL>
    static Flow* createFlow(System* s1,System* s2,std::string str) {
        return FlowImpl::createFlow<T_FLOW_IMPL>(s1,s2,str);
    }
    //-----------------------------------

    virtual double executeFunction()=0;
    virtual System* getTargetSys()=0;
    virtual System* getSourceSys()=0;
    virtual std::string getName()=0;
    virtual void changeTargetSys(SystemIterator)=0;
    virtual void changeSourceSys(SystemIterator)=0;
    virtual void changeTargetSys(System*)=0;
    virtual void changeSourceSys(System*)=0;

};

#endif

flowImpl.h

#include "flow.h"
#ifndef TRAB_INDIVIDUAL_FLOWIMPL_H
#define TRAB_INDIVIDUAL_FLOWIMPL_H

class ModelImpl;

class FlowImpl : public Flow {
    friend ModelImpl;
    friend Flow;

private:
    FlowImpl();
    FlowImpl(System*,System*,std::string);
    FlowImpl(Flow*,std::string);
    std::string name;
    System* source_sys;
    System* target_sys;

    template <typename T_FLOW_IMPL>
    static Flow* createFlow()  {
        Flow* f = new T_FLOW_IMPL();
        return f;
    }

    template <typename T_FLOW_IMPL>
    static Flow* createFlow(System*,System*,std::string)  {
        Flow* f = new T_FLOW_IMPL(s1,s2,str);
        return f;
    }

protected:
    double getSourceQ();
    double getTargetQ();

public:
    virtual ~FlowImpl();
    bool operator==(FlowImpl&);
    FlowImpl& operator=(const FlowImpl&);

    virtual double executeFunction()=0;
    System* getTargetSys() override;
    System* getSourceSys() override;
    std::string getName() override;
    void changeTargetSys(SystemIterator) override;
    void changeSourceSys(SystemIterator) override;
    void changeTargetSys(System*) override;
    void changeSourceSys(System*) override;
};

#endif

Я попытался использовать прямое объявление, но безуспешно, потому что я не могу переслать объявление метода другого класса (являющегося FlowImpl :: createFlow ()), только всего класса.

Моя цель в этих статических методах состоит в том, чтобы создать фабрику методов со статическими членами, использующими интерфейсы, и, поскольку я не могу использовать «виртуальный» для статических шаблонных методов, единственным вариантом было реализовать его на интерфейсе и внутри вызова реализации. тот же статический метод, но для подкласса, у которого есть атрибуты для распределения. Как я уже сказал, я не могу этого сделать, потому что методы шаблона не могут быть реализованы в другом файле, и если я определю его внутри заголовка, это вызовет циклическую зависимость с помощью flowImpl.h.

Спасибо за чтение! Пожалуйста, сообщайте о любых неясностях или отсутствии информации, чтобы я мог уточнить это.

1 Ответ

0 голосов
/ 01 июля 2018

Удалите #include из flowImpl.h из flow.h и объявите метод класса шаблона вперед:

class Flow {
public:

    // ...

    template <typename T_FLOW_IMPL>
    static Flow* createFlow();

Затем завершите работу в flowImpl.h, после объявления класса реализации:

class flowImpl {

// ...

};

template <typename T_FLOW_IMPL>
static Flow* Flow::createFlow() {
    return FlowImpl::createFlow<T_FLOW_IMPL>();
}

Сделайте то же самое для другого метода шаблона. Обратите внимание, что все, что нужно для вызова этих методов класса, должно включать заголовочный файл flowImpl.h.

...