GCC lets you forward declare a struct with "class /name/"

This is a discussion on GCC lets you forward declare a struct with "class /name/" within the C++ Programming forums, part of the General Programming Boards category; I'm interested to know whether this is strictly legal and if so why. Could it be a bug in GCC? ...

  1. #1
    C++ Junkie Mozza314's Avatar
    Join Date
    Jan 2011
    Location
    Australia
    Posts
    174

    GCC lets you forward declare a struct with "class /name/"

    I'm interested to know whether this is strictly legal and if so why. Could it be a bug in GCC? Surely not?

    Code:
    #include <iostream>
    using namespace std;
    
    class A;
    
    void Foo(A& a);
    
    struct A
    {
        int x;
    };
    
    int main()
    {
        A a;
        a.x = 3;
        Foo(a);
        return 0;
    }
    
    void Foo(A& a)
    {
        cout << a.x << endl;
    }

  2. #2
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,160
    I don't know what the standard says about it, but a class and a struct are exactly the same except for the default protection. Since this is a forward-declaration, not a definition, the default protection doesn't enter into it and the two things are for all purposes identical.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,529
    The stuff in 7.1.5.3 is used to make class names:
    The class-key or enum keyword present in the elaborated-type-specifier shall agree in kind with the declaration to which
    the name in the elaborated-type-specifier refers. This rule also applies to the form of elaborated-type-specifier that
    declares a class-name or friend class since it can be construed as referring to the definition of the class. Thus, in any
    elaborated-type-specifier, the enum keyword shall be used to refer to an enumeration (7.2), the union class-key shall be
    used to refer to a union (clause 9), and either the class or struct class-key shall be used to refer to a class (clause 9)
    declared using the class or struct class-key.
    As for what a class-key is, if you look that up too, it is a term defined by a list which includes the struct, class and union keywords. So a struct forward declaration could ultimately refer to a class definition, and vice versa, but only union refers to a union, legally speaking.

  4. #4
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,145
    And even if it's illegal construct, it's still not a GCC bug.

    The standard only says compilers must accept legal C/C++, not that they have to reject illegal C/C++.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    5,871
    Quote Originally Posted by cyberfish View Post
    And even if it's illegal construct, it's still not a GCC bug.
    It is a legal construct in this case.
    Quote Originally Posted by cyberfish View Post
    The standard only says compilers must accept legal C/C++, not that they have to reject illegal C/C++.
    The standards do specify that violations of syntax rules or constraints must be diagnosed i.e. identified, and (implementation-defined) diagnostic messages produced.

    One dictionary definition of "rejection" is "an act of, or leading to, discarding as unsatisfactory or imperfect". Issuing a diagnostic can therefore be viewed as an act of rejection.
    Right 98% of the time, and don't care about the other 3%.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,892
    Note, however, that while GCC is perfectly compliant here, Visual Studio is not! In particular, VS mangles classes and structs in incompatible ways. That is, if you have one file:
    Code:
    class A;
    void fun(A *);
    A* createA();
    
    int main() {
      A *pa = createA();
      fun(pa);
    }
    and another file:
    Code:
    struct A {
    };
    void fun(A *)
    {}
    A *createA() {
      return new A;
    };
    then in Visual Studio, this program will not link! This is incorrect, but they just can't solve the problem because it would be a major ABI breakage on their part.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    C++ Junkie Mozza314's Avatar
    Join Date
    Jan 2011
    Location
    Australia
    Posts
    174
    Quote Originally Posted by CornedBee View Post
    then in Visual Studio, this program will not link! This is incorrect, but they just can't solve the problem because it would be a major ABI breakage on their part.
    This is what happened at work the other day and prompted me to post this. We maintain a codebase that works with gcc and visual studio, though most developers spend most of their time on linux with gcc and for the most part rely on automated builds of visual studio. When we found out this was breaking the windows builds, we all thought... wtf why did this compile with gcc??

    Don't get me wrong, I'll take my linux/gcc environment over windows/visual studio any day, but on this specific point, it's a shame and I'm confused by the fact that the standard is like this, because visual studio's behaviour makes a lot more sense to me.

    I mean, wouldn't anyone prefer to have their code forward declare a struct with the struct keyword? If you're only building with gcc your compiler will never point this out despite such code being very likely (even certainly?) a mistake.

  8. #8
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,529
    It's probably only that way because C++ has to compile C. It makes sense to be straight forward like you say, but C++ has two keywords for the same feature, as brewbuck was keen to point out using different words, because the only difference is what default member protection you get using either one. I'd rather Microsoft follow the standard on little issues like these, but what else can we do but complain.

  9. #9
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    452
    Quote Originally Posted by whiteflags View Post
    I'd rather Microsoft follow the standard on little issues like these, but what else can we do but complain.
    We stopped using Windows.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  10. #10
    C++ Junkie Mozza314's Avatar
    Join Date
    Jan 2011
    Location
    Australia
    Posts
    174
    Quote Originally Posted by whiteflags View Post
    It's probably only that way because C++ has to compile C.
    Why would you need to be able to forward declare a struct with the class keyword or vice versa to be able to compile C?

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,892
    Quote Originally Posted by Mozza314 View Post
    Don't get me wrong, I'll take my linux/gcc environment over windows/visual studio any day, but on this specific point, it's a shame and I'm confused by the fact that the standard is like this, because visual studio's behaviour makes a lot more sense to me.
    That's because your mental model differs from the language's view: as far as C++ is concerned, there is no such thing as a "struct". There's just classes introduced with the struct keyword.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    5,871
    Quote Originally Posted by CornedBee View Post
    That's because your mental model differs from the language's view: as far as C++ is concerned, there is no such thing as a "struct". There's just classes introduced with the struct keyword.
    It's actually the other way around, historically. C++ first specified classes as structs with different (private versus public) default access.

    Incidentally, a forward declaration of a class (or a struct) can be done using either the struct or class keywords. At least, in standard C++.

    Clearly, the Microsoft ABI requires things to be done differently. It escapes me why that should affect end-user code though. It is not exactly a big leap for a compiler to map class and struct keywords in code to the same output (eg name mangling) that complies with requirements of an ABI.
    Right 98% of the time, and don't care about the other 3%.

  13. #13
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,892
    Quote Originally Posted by grumpy View Post
    Clearly, the Microsoft ABI requires things to be done differently. It escapes me why that should affect end-user code though. It is not exactly a big leap for a compiler to map class and struct keywords in code to the same output (eg name mangling) that complies with requirements of an ABI.
    Name mangling rules are part of the ABI.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Does gcc hate Forward declarations?
    By SevenThunders in forum C++ Programming
    Replies: 12
    Last Post: 03-16-2009, 02:03 PM
  2. Replies: 1
    Last Post: 12-03-2008, 02:10 AM
  3. how do you resolve this error?
    By -EquinoX- in forum C Programming
    Replies: 32
    Last Post: 11-05-2008, 03:35 PM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Bi-Directional Linked Lists
    By Thantos in forum C Programming
    Replies: 6
    Last Post: 12-11-2003, 09:24 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21