views:

388

answers:

3

Consider the following example. It consists of two header files, declaring two different namespaces:

// a1.h
#pragma once
#include "a2.h"

namespace a1 
{
    const int x = 10;
    typedef a2::C B;
}

and the second one is

// a2.h    
#pragma once
#include "a1.h"

namespace a2 {
  class C {
  public:
    int say() {
      return a1::x; 
    }
  };
}

And a single source file, main.cpp:

#include <iostream>
#include "a1.h"
#include "a2.h"

int main()
{
  a2::C c;
  std::cout << c.say() << std::endl;
}

This way it doesn't compile (tried GCC and MSVC). The error is that a1 namespaces is not declared (C2653 on Windows). If you change include order in main.cpp this way:

#include "a2.h"
#include "a1.h"

you get a symmetric error message, i.e. a2 namespace is not declared.

What's the problem?

+3  A: 

Just a guess, but your include reference is circular. Meaning the compiler can't figure out which header to compile first. a1 references a2 which references a1.

If possible, merge/reorganize the files so that there is a non-circular chain of includes.

Hope that helps!

Zachary Yates
You are thinking my thoughts. Please return them when you're finished.
Marcin
+9  A: 

You need to use a forward declaration in your header files because you have a circular reference. Something like this:

// a1.h
#pragma once

namespace a2 {
    class C;
}

namespace a1 
{
    const int x = 10;
    typedef a2::C B;
}
Greg Rogers
+1  A: 

When you include a1.h first, it immediately tries to include a2.h before declaring anything

a2.h references something in namespace a1 that hasn't been declared yet

When you include a2.h first, it immediately tries to include a1.h before declaring anything

a1.h references something in namespace a2 that hasn't been declared yet

Removing the typedef from a1.h, which you aren't using, and not including a2.h removes the cycle.

Or as by the other commenter, forward declare class C.

// a1.h
#pragma once
//#include "a2.h"

namespace a1 
{
    const int x = 10;
//    typedef a2::C B;
}