How to resolve include dependency with template method in template class?

Viewed 35

I have a three library classes each in separate file's:

File S.h:

#pragma once
#include "A.h"
class S
{
    A<int> a;
};

File: A.h:

#pragma once

#include "S.h"
#include "E.h"

template<typename T>
class A
{
public:
    template<int N>
    void foo()
    {
        E c;
    }
};

File E.h:

#pragma once

#include "S.h"
class E
{
public:
    S m_s;
};

When user write a code like this:

//#include "A.h"
#include "S.h"
#include "E.h"


int main()
{
    S s;
    E c;
    c.m_s = s;
}

It gets an error like: 'm_s': unknown override specifier.

Because of the after preprocessing class S; the definition appears below the class E; (which is use class S as the class member)

If I uncomment the first include, the problem will be slowed but for me, it's not a good solution. Another way is it's a hidden member of class E in something like PImpl, but it's not possible also due to some reasons.

Is there exist another solution for this problem?

1 Answers

Your includes are circular. A.h should not include S.h. And A.h including E.h is a problem too.

Here is what the compiler sees:

// from #include "S.h"
  // from #include "A.h"
    // #include "S.h"
    // #pragma once, so nothing
  // from #include "E.h"
    // from #include "S.h"
    // #pragma once, so nothing
class E
{
public:
    S m_s;
};

template<typename T>
class A
{
public:
    template<int N>
    void foo()
    {
        E c;
    }
};

class S
{
    A<int> a;
};

// from #include "E.h"
  // #pragma once, so nothing

int main()
{
    S s;
    E c;
    c.m_s = s;
}

When you define E the class S has not been declared.

Why does A.h include S.h? It's not using it. That removes one loop.

The other loop goes through E. I think you can declare A::foo() and A<int>::foo() and define the later in the A.cpp file. Then you can break the second loop.


Alternatively merge the three headers and lift the E into the template:

template<typename T, typename E>
class A
{
public:
    template<int N>
    void foo()
    {
        E c;
    }
};

template<typename E>
class S
{
    A<int, E> a;
};

class E
{
public:
    S<E> m_s;
};
Related