10
votes

As we know, struct and class are interchangeable in many places in the language. Confusingly, the keywords themselves do not necessarily correspond to the language used in the standard. For example, in draft standard N4567 [class]/10,

A POD struct109 is a non-union class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types). Similarly, a POD union is a union that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types). A POD class is a class that is either a POD struct or a POD union.

In over-simplified terms, struct and class are interchangeable in the following cases:

  • declaration of a "class"
  • declaration of a scoped enumeration type
  • elaborated type specifier unless the "class" was declared with union

However, struct explicitly cannot be used in a template declaration to introduce type template parameters:

template <struct T> // error

I'm unable to see any significant difference between struct and class, even in the POD example above because a POD struct as defined in the standard can be declared with either struct or class.

[class]/8 A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class. A standard-layout union is a standard-layout class defined with the class-key union.

This seems rather redundant and confusing while introducing a glaring inconsistency.

I have two questions:

  1. Are there any technical differences that I have missed that significantly distinguish struct and class?

  2. What is the rationale, if any, behind this clumsiness?

I'm ignoring the difference between default access specifiers because everyone knows that already.

2
Does it also puzzle you, that you can have template<typename T>, but not typename T{};?eerorika
@user2079303 and (before C++1z) template < template<typename> class C >, but not template < template<typename> typename C >Revolver_Ocelot
@Martin: No, the OP already knows the differences (he's pointed them all out).Benjamin Lindley
Can we take the question up a notch and ask if the standard actually prescribes and difference other than the default access? That is, if you had two headers, one of which declared the type as a struct T with members and one which declared it as a class T with all public members, would both link correctly to an object file that implemented the T and the T::... members?Rob Starling

2 Answers

8
votes

Why do both struct and class exist in C++?

A reason for existence of struct is for compatibility with C.

Why then, did "C with Classes" introduce the new keyword class when you could use struct for the same thing, you may ask. See this SO answer for plausible speculation. In short, it's probably because there was desire for emphasis on OOP in which class is a widely used term. Only Stroustrup may know for certain.

Confusingly, the keywords themselves do not necessarily correspond to the language used in the standard

What needs to be understood, is that the concept of a class is not one and the same with the keyword class.

There are three keywords for declaring classes. These keywords known as class-keys are class, struct and union. The non-union classes that are declared with either class or struct are exactly the same thing, except for . Union classes are different from non-union classes.

However, struct explicitly cannot be used in a template declaration to introduce type template parameters

C++ re-uses keywords for different purposes in different contexts. class keyword in a class declaration context, is not entirely the same as class keyword in a template argument definition. One keyword being equivalent to another in one context does not make it equivalent in all contexts. The reason for reusing keywords in different but similar contexts (static is another example), is to avoid introducing new keywords, which introduces more holes with compatibility with C (or earlier C++ standard) that does not have the new keywords.

The reason why class keyword was reused in the context of template type arguments was probably because classes are types, and therefore typically used as type parameters. There is also a typename keyword, which was added later and is (almost) interchangeable with class in template type argument declaration, but also used elsewhere (dependent type names) where class is not used. See this answer for a link and a summary about why a separate keyword was added to that context.

Why struct is not used in the context as an equivalent, you may ask. Well, that's another question to Stroustrup or the committee. It's an opposite choice than what committee did when enum class/enum struct was introduced.

I'm unable to see any significant difference between struct and class

Good. There isn't any except for

This seems rather redundant and confusing while introducing a glaring inconsistency.

I see no inconsistency in the quote from the standard. I see redundancy and I suspect that the redundancy exists to make it extra clear that a class declared with the keyword struct is still a class.

  1. Are there any technical differences that I have missed that significantly distinguish struct and class?

I've already answered, but to be clear, there is no difference between classes declared with struct and class keywords, beyond .

the difference with the default access specifier (as you already know, and also described here), which is their only difference.

5
votes

Why do both struct and class exist in C++?

struct comes from C, and exists in C++ mainly for reasons of compatibility with the C programming language.

Are there any technical differences that I have missed that significantly distinguish struct and class?

The main difference between a struct and a class is that for the struct its members have public access by default whereas for the class its members have private access by default.

The keyword class used in template arguments does not define a class but rather a non type template argument and can be used interchangeably with keyword typename.

As for why you can't use struct keyword for specifying a non type template argument, the reasons are historical and I guess you have to ask Bjarne for it :) or refer to this SO answer for info behind the scenes.