ofir agranat
ofir agranat

Reputation: 90

Forward declaration within a class (not a nested class)

I came across this odd forward declaration (or something) where instead of having a normal:

class A;
class B{
    A* var;
}

You can do

class B{
   class A* var;
}

Now this might be an elaborated type specifier, but I'm not sure about that. I've tried it myself and I had no issues, even made my code a lot more cleaner, but I'm afraid it may cause scoping issues that I'm currently unaware of.

Does anyone have an insight on this? is this a valid forward deceleration?

example: https://youtu.be/EIptJ0YrYg0?t=412

Upvotes: 3

Views: 148

Answers (3)

nop666
nop666

Reputation: 603

Note that the doc says:

Note that a new class name may also be introduced by an elaborated type specifier which appears as part of another declaration, but only if name lookup can't find a previously declared class with the same name.

Thus, if class B is enclosed in a namespace and no previous forward declaration of A is performed, then it refers to n2::A that will have to be defined.

Upvotes: 2

super
super

Reputation: 12928

Yes, it's a valid forward declaration. It's called an elaborate type specifier.

To quote from elaborated type specifier from cppreference.

If the name lookup does not find a previously declared type name, the elaborated-type-specifier is introduced by class, struct, or union (i.e. not by enum), and class-name is an unqualified identifier, then the elaborated-type-specifier is a class declaration of the class-name.

It can also be used to refer to an already declared class even if it's name is hidden by non-type declaration.

Upvotes: 1

Now this might be an elaborated type specifier, but I'm not sure about that.

It is. In fact, class A; is a declaration to uses an elaborate class specifier.

but I'm afraid it may cause scoping issues that I'm currently unaware of

The only scoping related point you should be aware of is that if the elaborate type specifier (that is not a declaration by itself) is the first time class is referenced, the behavior is the same as if you introduced a forward declaration to the nearest namespace or block scope. So for instance

namespace N {
  class foo {
     class bar {
       void func(class baz*);
     };
  };
};

... is the same as

namespace N {
  class baz;
  class foo {
     class bar {
       void func(baz*);
     };
  };
};

Upvotes: 1

Related Questions