Circular dependency with template function

circular dependency c++
how to fix circular dependency
c++ find circular dependency
ue4 c++ circular dependency
how to resolve circular dependency in spring like class a has an object of class b and vice versa
cyclic inclusion c++
circular references c++
c++ header dependency

I have a class A with the following declaration (A.h file):

#ifndef __A_DEFINED__
#define __A_DEFINED__

class A
{
public:
  template<typename T> inline void doThat() const;
};

#endif

and a class B deriving from that class (B.h file):

#ifndef __B_DEFINED__
#define __B_DEFINED__

#include <iostream>
#include "A.h"

class B : public A
{
public:
  void doThis() const { std::cout << "do this!" << std::endl; }
};

#endif

So far, so good. My issue is that the function A::doThat() uses B::doThis():

template<typename T> inline void A::doThat() const { B b; b.doThis(); }

Usually, the circular dependency would not be an issue because I would just define A::doThat() in the .cpp file. In my case however, doThat is a template function so I can't do that.

Here are the solutions I have envisioned so far:

  1. Defining the template function A::doThat() in a .cpp file. The issue with that is that I need to instantiate explicitly all the calls with various template arguments (there might be many in the real case).

  2. After the declaration of the A class in A.h, add #include "B.h" and then define the A::doThat() function. This works fine in visual studio but g++ does not like it.

Is there a neat way to solve this problem?

EDIT: In the real case, there is not just one child class B, but several (B, C, D, etc.) The function A::doThat() depends on all of them. The function B::doThis() is also templated.

A default template parameter for the B class could work:

#include <iostream>

// include A.h
class B;

class A
{
public:
    template<typename T, typename U = B> inline void doThat() const 
    {
        U b; b.doThis();
    }
};

// include B.h
class B : public A
{
public:
    void doThis() const { std::cout << "do this!" << std::endl; }
};

// main
int main()
{
    A a;
    a.doThat<int>();
}

How to handle circular dependencies with templates in C++, When the compiler sees a template (class and method), it must know Here is one quirk, circular dependencies with templated classes and  Resource Manager identifies circular dependencies during template validation. If you receive an error stating that a circular dependency exists, evaluate your template to see if any dependencies aren't needed and can be removed.

Usually the best way to allow a parent to call a child function is to declare the function as a pure virtual function in the parent and override it in the children.

#include <iostream>

class A
{
public:
    virtual ~A() = default;
    template<typename T> inline void doThat() const
    {
        // do some other stuff
        doThis();
    }
    virtual void doThis() const = 0; // pure virtual function
};

class B: public A
{
public:
    void doThis() const override
    {
        std::cout << "do this!" << std::endl;
    }
};

int main()
{
    B b;
    A* ap = &b;
    ap->doThat<int>();
}

How to Handle Circular Dependencies with Templates in C++ , Why not optimize and use virtual function pointers. The events can be handled through a simple array of functions labeled with maybe enum or  The next image illustrates where the circular dependency resides in the template. You can see that security group rules have a Ref to the security group itself. This means this resource needs to be created before it can add the rule defined.

The following does work with g++:

File A.h:

#ifndef __A_DEFINED__
#define __A_DEFINED__

class A
{
public:
  template<typename T> inline void doThat() const;
};

#include "B.h"

template<typename T> inline void A::doThat() const { B b; b.doThis(); }

#endif

File B.h:

#include <iostream>

#include "A.h"

// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__

class B : public A
{
public:
  void doThis() const { std::cout << "do this!" << std::endl; }
};

#endif

File test_A.cpp:

// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.

int main() {
    A a;
    a.doThat<int>();
}

File test_B.cpp:

// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.

int main() {
    B b;
    b.doThat<int>();
    b.doThis();
}

Alternative Idea:

I do not know whether you (or some coding conventions) insist on separate header files for each class, but if not the following should work:

You can put the definitions of class A and class B and of the member function template A::doThat<typename>() (in this order) together in one header file AandB.h (or whatever name you like).

Circular dependency, If you create a bi-directional composition between two templates (A and B), you get BETWEEN TEMPLATE CLASSES CAUSES CIRCULAR DEPENDENCY  Getting around circular CloudFormation dependencies. Several posts complain about the inability of CloudFormation to apply a Lambda event function to an S3 Bucket with an dynamically generated name. The standard UseCase is an S3 Bucket with a Lambda event notification. In this special case the Bucket has a dynamically generated name.

This cries for polymorphism. There are two options using polymorphism:

  1. Dynamic polymorphism, i.e. make A an abstract base class and call doThis() virtually:

    struct A
    {
        virtual void do_this() const = 0;
        template<typename T>
        void doThat() const { doThis(); }
    };
    
    struct B : A
    {
        void doThis() const override { /* ... */ }
    };
    

    Of course, this only works if doThis() is not templated. If you need that, you could use

  2. Static polymorphism, i.e. CRTP, when

    template<typename Derived>
    struct A
    {
        template<typename T>
        void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); }
    };
    
    struct B : A<B>
    {
        template<typename T>
        void doThis() const { /* ... */ }
    };
    

If (as in your example code) B::doThis() is not called for the same object, but for some temporary, you could

template<typename typeB>
struct A
{
    template<typename T>
    void doThat() const { typeB b; b.template doThis<T>(); }
};

pi98965: composition between template classes causes circular , functions for the new server-class. In a pure dynamic We get an infinite circular dependency between the template classes. It is impossible to  To solve a circular dependency: In your template, find the resource identified in the circular dependency. For that resource, examine the dependsOn property and any uses of the reference function to see which resources it depends on. Examine those resources to see which resources they depend on. Follow the dependencies until you notice a resource that depends on the original resource.

Circular dependencies in Templates - better solution? - C / C++, [C++] Circular Dependency with Template Classes foo.h * Foo is a template class and does not have a * compiled component. (Linear progression/ Bulgarian method are two styles of increasing training intensity while varying intervals and  Circular dependencies are natural in many domain models where certain objects of the same domain depend on each other. However, in software design, circular dependencies between larger software modules are considered an anti-pattern because of their negative effects. Despite this such circular (or cyclic) dependencies have been found to be widespread among the source files of real-world software.

[C++] Circular Dependency with Template Classes , Description This template produces circular dependency: AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-​10-31  A possible solution is using nested IF functions with a circular reference in the second IF: =IF (B2="yes", IF (C2="",NOW (), C2), "") Where B2 is the delivery status, and C2 is the cell where you want a timestamp to appear.

Circular dependency when Function has Environment and S3 Event , Define the order for deploying resources in ARM templates You define a dependency with the dependsOn element, or by using the reference function. Resource Manager identifies circular dependencies during template  What is your dependencies for row 199? Finding a circular dependency (if there really is one) can be a bit of a pain, especially when you start factoring parent and child rows.

Comments
  • Unrelated: Any identifier with two underscores in a row is reserved for use by the implementation. Use them at your own risk. More information here: What are the rules about using an underscore in a C++ identifier?
  • This would work only with a default template parameter or even if define the function here? I am saying this because in the real case, doThat() depends on B, but also on children C, D and E.
  • @Touloudou That sounds like a related, but different question with a different answer.
  • The issue here is that the doThis() function should also be templated in the real case. It means this would be a virtual template function, which is not OK in current c++.
  • @Touloudou that's really important information to have in the question. You should edit the question and add it. If it is templated without (or with simple) parameters you can abstract the templated function behind a regular one.
  • @Touloudou I got your problem working with g++ also according to your idea 2. I had to move the include guard (see the comment in B.h).