struct X {int a; };
struct Y {int a; };
X a1;
Y a2;
int a3;
declares three variables of three different types.
This implies that
a1 = a2; // error: Y assigned to X
a1 = a3; // error: int assigned to X
are type mismatches, and that
int f(X);
int f(Y);
declare overloads ([over]) named f and not
simply a single function f twice.
For the same reason,
struct S {int a; };
struct S {int a; }; // error: double definition
is ill-formed because it defines S twice.
It can be necessary to use an elaborated-type-specifier
to refer to a class
that belongs to a scope in which its name is also bound to
a variable, function, or enumerator ([basic.lookup.elab]).
[Example 2: struct stat {// ...};
stat gstat; // use plain stat to define variableint stat(struct stat*); // stat now also names a functionvoid f(){struct stat* ps; // struct prefix needed to name struct stat
stat(ps); // call stat function} — end example]
[Example 3: struct s {int a; };
void g(){struct s; // hide global struct s with a block-scope declaration
s* p; // refer to local struct sstruct s {char* p; }; // define local struct sstruct s; // redeclaration, has no effect} — end example]
Such declarations allow definition of classes that refer to each other.
[Example 4: class Vector;
class Matrix {// ...friend Vector operator*(const Matrix&, const Vector&);
};
class Vector {// ...friend Vector operator*(const Matrix&, const Vector&);
};