1

I have compiled the code below and run it successfully with Microsoft Visual Studio 2008's compiler. However, the compiler I need to use in production (due to project constraints) is the Intel C++ compiler 11.1.065.

So, my question is: Is some part of the syntax incorrect in the following code (and the visual studio compiler just works with it) or does the version of the Intel Compiler that I am using just lack support? If so, would anyone be so kind as to provide syntax that the version 11.1.065 of the Intel Compiler can understand? Thank you in advance!

Header file A.h:

#ifndef A_H
#define A_H

#include "B.h"

//forward declarations
template <typename T> class B;
// I tried adding the following line (even though it is
//    not needed by the visual studio compiler:
//template <typename T> B<T>::B(A<T> const&);

template <typename T>
class A
{
private:
    int m_var;
public:
    A() : m_var(1) {}
    friend B<T>::B(A<T> const& x);
};
#endif //A_H

Header file B.h:

#ifndef B_H
#define B_H

#include "A.h"

template <typename T> class A;

template <typename T>
class B
{
private:
    int m_var;
public:
    B(A<T> const& x)
        : m_var(x.m_var)
    {}
};
#endif //B_H

Body file with Main Function:

#include "B.h"
#include "A.h"

int main(int argc, char* argv[])
{
    A<int> a;
    B<int> b(a);

    return 0;
}

The error returned by the Intel compiler is:

.\A.h(16): error: expected a ")"
      friend B<T>::B(A<T> const& x);
                          ^

EDIT: Because there is so much focus surrounding whether or not this is caused by the multiple inclusion, the above code expands to the following which shows that the multiple inclusion should not impact the code:

//<#include "B.h" expanded>
#ifndef B_H
#define B_H

//<#include "A.h" expanded>
#ifndef A_H
#define A_H

//<#include "B.h" expanded>
//   Because B_H is defined, B.h's contents are not expanded
//</#include "B.h" expanded>

//forward declarations
template <typename T> class B;
// I tried adding the following line (even though it is
//    not needed by the visual studio compiler:
//template <typename T> B<T>::B(A<T> const&);

template <typename T>
class A
{
private:
    int m_var;
public:
    A() : m_var(1) {}
    friend B<T>::B(A<T> const& x);
};
#endif //A_H
//</#include "A.h" expanded>

template <typename T> class A;

template <typename T>
class B
{
private:
    int m_var;
public:
    B(A<T> const& x)
        : m_var(x.m_var)
    {}
};
#endif //B_H
//</#include "B.h" expanded>

//<#include "A.h" expanded>
//   Because A_H is defined, A.h's contents are not expanded
//</#include "A.h" expanded>

int main(int argc, char* argv[])
{
    A<int> a;
    B<int> b(a);

    return 0;
}
statueuphemism
  • 644
  • 2
  • 5
  • 13
  • 1
    Your have a mutual inclusion between your headers. [This Q&A](http://stackoverflow.com/questions/14909997/why-arent-my-include-guards-preventing-recursive-inclusion-and-multiple-symbol) should explain what is going on – Andy Prowl May 21 '13 at 18:16
  • @Andy I do have mutual inclusion. I also have header guards and forward declarations. Any other thoughts or am I missing something in thinking that the Q&A you listed does not help me with my problem? – statueuphemism May 21 '13 at 18:19
  • Well, the Q&A I linked explains why header guards do not help against mutual inclusions – Andy Prowl May 21 '13 at 18:21
  • @Andy It proposes that "You need forward declarations" as the solution to the problem. I have forward declarations. I apologize again if I am missing something. To note again, my code compiles in Microsoft Visual Studio 2008, but does not compile with the Intel Compiler version 11.1.065. – statueuphemism May 21 '13 at 18:23
  • It proposes "you need forward declarations", but the assumption is "and you need to remove the mutual inclusion". Honestly I can't see how the code you posted could compile on VC9, since it contains a mutual inclusion of headers (unless what you posted is not exactly what you have) – Andy Prowl May 21 '13 at 18:27
  • @Andy The code is copy and pasted directly from the solution where I was boiling down the problem. Please tell me why is this a necessary condition: "and you need to remove the mutual inclusion". That seems like a rather large assumption to make since the headers will only be included once per the include guards. At worst, I will have a complete definition of A by the time B is declared (rather than just a forward declaration of A) in its current state, no? The includes are redundant with the forward declarations, but they should not break anything. – statueuphemism May 21 '13 at 18:35
  • Well, the linked Q&A explains it all. [Here](http://ideone.com/V5h7b1) you can see your code compiling after removing the mutual inclusion. – Andy Prowl May 21 '13 at 18:41
  • @Andy I have tried removing the include guards in addition to ensuring class A is defined first. I get the same error regardless. I know the code compiles with Visual Studio 2008 and might work with some other compilers, but my primary concern is how to make this code work with the Intel Compiler. If there is no way that you know of, I certainly appreciate your effort and attempts to help, but I do believe my problem differs from the solution that you have suggested. – statueuphemism May 21 '13 at 19:07
  • OK, then I don't know what could be, sorry :( – Andy Prowl May 21 '13 at 19:10

1 Answers1

1

Remove the forward declaration of B from A.h and reverse the order of includes.

#include "B.h"
#include "A.h".

You cannot make individual member functions friends until they have been declared. Hence B's ctor (and hence B) needs to be visible before you declare it as friend in A. However, B can get by with just a fwd declaration of A because it uses only a reference to A.

Hence you need to reverse the order of includes.

user93353
  • 13,733
  • 8
  • 60
  • 122
  • I tried your solution. I achieved the exact same results as posted in my original question: Compiles with Visual Studio 2008, Fails with Intel C++ 11.1.065 (exact same error message). – statueuphemism May 21 '13 at 18:42