[diff.class]

# Annex C (informative) Compatibility [[diff]](./#diff)

## C.7 C++ and C [[diff.iso]](diff.iso#diff.class)

### C.7.7 [[class]](class "11 Classes"): classes [diff.class]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3483)

**Affected subclause:** [[class.name]](class.name) [see also [[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")]  

**Change:** In C++, a class declaration introduces the class name into the scope where it is
declared and hides any object, function or other declaration of that name in an enclosing
scope[.](#1.sentence-2)

In C, an inner scope declaration of a struct tag name never hides the name of an
object or function in an outer scope[.](#1.sentence-3)

[*Example [1](#example-1)*: int x[99];void f() {struct x { int a; }; sizeof(x); /* size of the array in C *//* size of the struct in *C++* */} â *end example*]

  


**Rationale:** This is one of the few incompatibilities between C and C++ that
can be attributed to the new C++ name space definition where a
name can be declared as a type and as a non-type in a single scope
causing the non-type name to hide the type name and requiring that
the keywords class, struct, union or enum be used to refer to the type name[.](#1.sentence-4)

This new name space definition provides important notational
conveniences to C++ programmers and helps making the use of the
user-defined types as similar as possible to the use of fundamental
types[.](#1.sentence-5)

The advantages of the new name space definition were judged to
outweigh by far the incompatibility with C described above[.](#1.sentence-6)

  


**Effect on original feature:** Change to semantics of well-defined feature[.](#1.sentence-7)

  


**Difficulty of converting:** Semantic transformation[.](#1.sentence-8)

If the hidden name that needs to be accessed is at global scope,
the ​::​ C++ operator can be used[.](#1.sentence-9)

If the hidden name is at block scope, either the type or the struct
tag has to be renamed[.](#1.sentence-10)

  


**How widely used:** Seldom[.](#1.sentence-11)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3523)

**Affected subclause:** [[class.copy.ctor]](class.copy.ctor)  


**Change:** Copying volatile objects[.](#2.sentence-1)

The implicitly-declared copy constructor and
implicitly-declared copy assignment operator
cannot make a copy of a volatile lvalue[.](#2.sentence-2)

[*Example [2](#example-2)*:

The following is valid in C:struct X { int i; };volatile struct X x1 = {0};struct X x2 = x1; // invalid C++struct X x3;
x3 = x1; // also invalid C++

â *end example*]

  


**Rationale:** Several alternatives were debated at length[.](#2.sentence-4)

Changing the parameter tovolatileconstX& would greatly complicate the generation of
efficient code for class objects[.](#2.sentence-5)

Discussion of
providing two alternative signatures for these
implicitly-defined operations raised
unanswered concerns about creating
ambiguities and complicating
the rules that specify the formation of
these operators according to the bases and
members[.](#2.sentence-6)

  


**Effect on original feature:** Deletion of semantically well-defined feature[.](#2.sentence-7)

  


**Difficulty of converting:** Semantic transformation[.](#2.sentence-8)

If volatile semantics are required for the copy,
a user-declared constructor or assignment must
be provided[.](#2.sentence-9)

If non-volatile semantics are required,
an explicitconst_cast can be used[.](#2.sentence-10)

  


**How widely used:** Seldom[.](#2.sentence-11)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3571)

**Affected subclause:** [[class.bit]](class.bit)  


**Change:** Bit-fields of type plain int are signed[.](#3.sentence-1)

  


**Rationale:** The signedness needs to be consistent among template specializations[.](#3.sentence-2)

For consistency,
the implementation freedom was eliminated for non-dependent types,
too[.](#3.sentence-3)

  


**Effect on original feature:** The choice is implementation-defined in C, but not so in C++[.](#3.sentence-4)

  


**Difficulty of converting:** Syntactic transformation[.](#3.sentence-5)

  


**How widely used:** Seldom[.](#3.sentence-6)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3587)

**Affected subclause:** [[class.nest]](class.nest)  


**Change:** In C++, the name of a nested class is local to its enclosing class[.](#4.sentence-1)

In C
the name of the nested class belongs to the same scope as the name of the outermost enclosing class[.](#4.sentence-2)

[*Example [3](#example-3)*: struct X {struct Y { /* ... */ } y;};struct Y yy; // valid C, invalid C++ â *end example*]

  


**Rationale:** C++ classes have member functions which require that classes
establish scopes[.](#4.sentence-3)

The C rule would leave classes as an incomplete scope mechanism
which would prevent C++ programmers from maintaining locality
within a class[.](#4.sentence-4)

A coherent set of scope rules for C++ based on the C rule would
be very complicated and C++ programmers would be unable to predict
reliably the meanings of nontrivial examples involving nested or
local functions[.](#4.sentence-5)

  


**Effect on original feature:** Change to semantics of well-defined feature[.](#4.sentence-6)

  


**Difficulty of converting:** Semantic transformation[.](#4.sentence-7)

To make the struct type name visible in the scope of the enclosing
struct, the struct tag can be declared in the scope of the
enclosing struct, before the enclosing struct is defined[.](#4.sentence-8)

[*Example [4](#example-4)*: struct Y; // struct Y and struct X are at the same scopestruct X {struct Y { /* ... */ } y;}; â *end example*]

All the definitions of C struct types enclosed in other struct
definitions and accessed outside the scope of the enclosing
struct can be exported to the scope of the enclosing struct[.](#4.sentence-9)

Note: this is a consequence of the difference in scope rules,
which is documented in [[basic.scope]](basic.scope "6.4 Scope")[.](#4.sentence-10)

  


**How widely used:** Seldom[.](#4.sentence-11)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/compatibility.tex#L3634)

**Affected subclause:** [[class.member.lookup]](class.member.lookup)  


**Change:** In C++, a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") may not be redeclared in a class definition after being used in that definition[.](#5.sentence-1)

[*Example [5](#example-5)*: typedef int I;struct S { I i; int I; // valid C, invalid C++}; â *end example*]

  


**Rationale:** When classes become complicated, allowing such a redefinition
after the type has been used can create confusion for C++
programmers as to what the meaning of I really is[.](#5.sentence-2)

  


**Effect on original feature:** Deletion of semantically well-defined feature[.](#5.sentence-3)

  


**Difficulty of converting:** Semantic transformation[.](#5.sentence-4)

Either the type or the struct member has to be renamed[.](#5.sentence-5)

  


**How widely used:** Seldom[.](#5.sentence-6)
