2

Does the standard (as of C++20) explicitly or implicitly allow using a different class-key when (forward-)declaring a class-name than when defining it? For the purpose of this question class-key shall be limited to class or struct, excluding union.

In other words, is this legal:

struct C;
class C{};
class S;
struct S{};

An answer should explicitly refer to the C++20 standard (or a suitable draft).


I couldn't find anything in the entire [class] section.

The only indication I could find is in [decl.type.elab.6] which first states:

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.

But to me it is unclear what kind means in this context. I suppose enum and struct are different kinds but are struct and class different kinds? I don't know. Anyway after some unrelated points about friends it goes on to say:

Thus, in any elaborated-type-specifier, the enum keyword shall be used to refer to an enumeration ([dcl.enum]), the union class-key shall be used to refer to a union ([class.union]), and either the class or struct class-key shall be used to refer to a non-union class ([class.pre]).

(emph added)

This sort of sounds as if struct and class were interchangeable, but I'm not sure about it.


According to code explorer it appears to be generally accepted by compilers.


Non-Duplicates

bitmask
  • 32,434
  • 14
  • 99
  • 159
  • Probably related/duplicate: https://stackoverflow.com/q/40738351/417197 – André Dec 05 '22 at 08:04
  • @André Ah yes. I searched previously to asking but didn't find anything. However, the related question has no answers that include standardese. – bitmask Dec 05 '22 at 08:06
  • Hence the comment, instead of a close vote. I've found a better one: https://stackoverflow.com/q/4866425/417197 – André Dec 05 '22 at 08:10
  • 1
    @justANewbstandswithUkraine No it doesn't as it refers to an unspecified version of the standard but one that is necessarily older than C++20 as per the date it was posted. Furthermore I do not believe any of the answers actually answers the question posed here. – bitmask Dec 05 '22 at 08:17
  • _An answer should explicitly refer to the C++20 standard_ Unless you explain why you expect change in C++20, this is an invalid requirement. At least, for complaining about dups. C++ is known to maintain backward compatibility. – Language Lawyer Dec 05 '22 at 09:37
  • @LanguageLawyer I care about C++20. If it is unchanged then it should still be present in C++20. However, answers that refer to old standards contain references that simply do not exist anymore, so I cannot verify that this behaviour is unchanged in C++20. I find it quite frankly presumptuous for you to dictate what is and isn't a valid requirement for a question that *I have*. – bitmask Dec 05 '22 at 09:41
  • In C++20, look in Section 9.2.8.3, para 1. The wording is a bit more complicated than in previous standards (consistent with the approach of indulging language lawyers in the last few years). But the equivalence of declarations `struct S;` and `class S;` and being able to follow that up with either (not both) `struct S {...};` or `class S{...};` has been part of C++ since the ARM was written, so it's not likely to change - changing that equivalence would break a lot of real-world code, retaining it does not. – Peter Dec 05 '22 at 10:02
  • @Peter Thanks. I already stumbled upon [dcl.type.elab](https://timsong-cpp.github.io/cppwp/n4861/dcl.type.elab) but I'm not sure which phrase you are referring to. I don't see where paragraph 1 makes a point about how to interchange class-key keywords. – bitmask Dec 05 '22 at 10:27
  • The example under that verse uses both `struct S` and `class S`. – duck Dec 05 '22 at 12:04
  • @duck Maybe this is a bit nitpicky, but Examples are non-authoritative as far as I know. – bitmask Dec 05 '22 at 12:06
  • _Examples are non-authoritative as far as I know_ The authoritative part is above the Example. Examples are intended to resolve doubts like your _This sort of sounds as if struct and class were interchangeable, but I'm not sure about it_ – Language Lawyer Dec 05 '22 at 13:29

1 Answers1

3

The standard explains this in 9.2.8.3.3 and clarifies it in the example, as Peter already pointed out in a comment to your question:

[...] either the class or struct class-key shall be used to refer to a non-union class [...]

struct S { } s;
class S* p = &s;    // OK

The compilers agree, as can be seen by the warning clang generates:

warning: 'C' defined as a struct here but previously declared as a class; this is valid, but may result in linker errors under the Microsoft C++ ABI [-Wmismatched-tags]

GCC has a faq entry:

Because it is not a bug, hence the warning is just noise. This is a dumb warning that only exists because the MS compiler has a bug that treats struct and class differently in mangled names. GCC (and Clang) correctly implement the C++ standard which says it doesn't matter.

Chronial
  • 66,706
  • 14
  • 93
  • 99