It depends on the exact rule. Violations of most rules related to incomplete class types in the core language section of the Standard must be diagnosed. Uses as a template argument to a Standard Library template are undefined behavior unless otherwise specified, which gives a bit more latitude to implementations.
These rules require diagnosis (since they are stated with "shall"):
[basic.def]/5:
In the definition of an object, the type of that object shall not be an incomplete type ([basic.types]), an abstract class type, or a (possibly multi-dimensional) array thereof.
[dcl.fct.def.general]/2:
The type of a parameter or the return type for a function definition shall not be a (possibly cv-qualified) class type that is incomplete or abstract within the function body unless the function is deleted ([dcl.fct.def.delete]).
[expr.ref]/4 (concerning the type of the operand expression before a .
operator):
The class type shall be complete unless the class member access appears in the definition of that class. [ Note: If the class is incomplete, lookup in the complete class type is required to refer to the same declaration ([basic.scope.class]). — end note ]
Since the built-in meaning of the ->
operator is defined with A->B
equivalent to (*A).B
, this also applies to ->
operator expressions.
[class.mem]/15:
The type of a non-static data member shall not be an incomplete type ([basic.types]), an abstract class type ([class.abstract]), or a (possibly multi-dimensional) array thereof. [ Note: In particular, a class C cannot contain a non-static member of class C, but it can contain a pointer or reference to an object of class C. — end note ]
[class.derived]/2 (concerning the list of base classes for a class definition):
A class-or-decltype shall denote a (possibly cv-qualified) class type that is not an incompletely defined class ([class.mem]); any cv-qualifiers are ignored.
There are more core language rules forbidding incomplete class types, but the above are the most commonly relevant ones. See also the non-normative list of contexts requiring a complete class in [basic.def.odr]/12.
I don't see a direct rule that a qualified-id scope::name
is ill-formed if scope
names an incomplete class type, but it just may be that the name lookup will certainly fail in that case, which is a diagnosable violation.
For the Standard Library, the overall prohibition on incomplete types as template arguments is [res.on.functions]/(2.5):
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, this document places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
As noted, C++17 added specific permission to instantiate class std::vector<T, Alloc>
, but none of its members, if T
is incomplete and Alloc
satisfies the "allocator completeness requirements" ([vector.overview]/4)