Incomplete type in nested name specifier

C++Language Lawyer

C++ Problem Overview


I tried to use incomplete type in nested name specifier as the following:

class A;

int b= A::c; // error: incomplete type ‘A’ used in nested name specifier

class A {
    static const int c=5;
};

There is says nothing about it in the 3.4.3/1 of N3797 working draft:

> The name of a class or namespace member or enumerator can be referred > to after the :: scope resolution operator (5.1) applied to a > nested-name-specifier that denotes its class, namespace, or > enumeration

So is that behavior implementation dependent?

C++ Solutions


Solution 1 - C++

Introduction

There are several places in the standard that implicitly implies that your code is ill-formed, but the below quotation speaks for itself:

>3.3.2p6 Point of declaration [basic.scope.pdecl] >>After the point of declaration of a class member, the member name can be looked up in the scope of its class.

The problem with your code isn't that you try to reach inside the body of an incomplete type, the problem is that you can only refer to a class member name after it has been declared.

Since your forward-declaration (of course) doesn't introduce any member named c, it is ill-formed to refer to such name.


The misleading diagnostic...

The diagnostic issued by both gcc and clang when being fed your code is somewhat misleading, and honestly I feel a bug report is in order.

foo.cpp:3:8: error: incomplete type 'A' named in nested name specifier


We are allowed to name an incomplete type in a nested-name-specifier, but as said; we are not allowed to refer to a member that has not yet been declared.

ill-formed:

class X {
  static int a[X::x];        // ill-formed, `X::x` has not yet been declared
  static int const x = 123;
};

legal:

class X {
  int const x = 123;
  int a[X::x]; // legal, `X` is incomplete (since we are still defining it)
               //        but we can still refer to a _declared_ member of it
};

Solution 2 - C++

I got the same error when accessing a member variable of a class that had been forward-declared in the header, but not included in the main from where I accessed it.

myClass.h

class FowardInclude; // has member "int x", but only forward-declared here

class MyClass {
public:
    void foo(int num);
}

main.cpp

#include "forwardInclude.h" // <-- This is the line I was missing
#include "myClass.h"

MyClass m;
m.foo(ForwardInclude::x);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2953119View Question on Stackoverflow
Solution 1 - C++Filip Roséen - refpView Answer on Stackoverflow
Solution 2 - C++ZciurusView Answer on Stackoverflow