-1

I have this class that compiles in VC14, but when I try to compile in gcc 4.8.5, it doesn't work, I get "error: C was not declared in this scope".

class A
{

};

class B : public A
{
   friend class C;
   friend class D;
private:
   class BB
   {
      std::list<C> c;
      std::list<D> d;
   };
};

class C : public B::BB
{

};

class D : public B::BB
{

};

I tried to forward declare "class C" before the definition of class B, but it gives me an error because it doesn't have the same definition as "class C : public B::BB", and I can't put that definition because BB is private... I'm not sure what to do.

Thanks

danny
  • 7
  • 1
  • `friend class BB { ...` is this a typo? You cannot declare/implement a class as friend like that. – scohe001 Aug 02 '19 at 16:23
  • 1
    Please provide a [mcve]. (Also, "C++11" is not a compiler.) – melpomene Aug 02 '19 at 16:24
  • Yes was a typo, sorry about that – danny Aug 02 '19 at 16:34
  • IMHO, `friend` classes add complexity. Can you redesign without needing `friend`? – Thomas Matthews Aug 02 '19 at 16:39
  • I recommend against nested classes; the increase the complexity of the code (in both reading and typing). – Thomas Matthews Aug 02 '19 at 16:40
  • 3
    This doesn't compile with any C++ compiler because of ..., missing semicolons, missing definition of List etc. This is not real code. We have no idea what is the real problem because we don't get to see the real code. – n. m. could be an AI Aug 02 '19 at 16:41
  • I fixed the code so that it works. I'm not allowed to change the original code, which was originally only for VC compiler, but now I'm porting the code to linux, and I get this error, and I can't share the real code because it's not my code. – danny Aug 02 '19 at 17:56

2 Answers2

2

Forward declarations that use friend are different from other forward declarations. Writing friend class C; within the definition of B declares that there is a class called C in the enclosing namespace (i.e., the global namespace) but does not actually introduce the name C into that scope. Therefore, you can't write something like List<C> because the name C cannot be found. You should do this:

class C;
class D;
class B : public A
{
   friend class C;
   friend class D;
private:
   class BB
   {
      List<C> c;
      List<D> d;
   }
}

The namespace-scope declarations actually introduce the names C and D into the global scope. Then, the friend declarations make those classes friends of B.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Why does it "compile in C++11" (whatever that means)? Could VS have some non-conformance here? Might be a valued addition to the answer though I think we need a better question first. – Lightness Races in Orbit Aug 02 '19 at 16:53
1

At the time you do

List<C> c;
List<D> d;

the compiler has no idea what C and D are--you haven't declared/implemented them yet!

You don't have to completely implement them, but you'll need to at least tell the compiler they're class that'll be implemented at some point. You can do that with:

class C;
class D;

Full working example (with some minor fixes like adding semicolons to make it compile): ideone

scohe001
  • 15,110
  • 2
  • 31
  • 51
  • I tried to do this, same as in your example, and I'm able to compile it in gcc 8, but not in gcc 4.8.5. It says that ‘class B::BB' is private. Is it because of the compiler version? – danny Aug 02 '19 at 17:53
  • The full error is "class B::BB’ is private within this context 'class C : public B::BB'". – danny Aug 02 '19 at 18:01