Consider these two programs and their attempted compilations.
#include <vector>
int main() {
std::vector<struct Typo> a; // Errors centered around `Typo` being an incomplete type
}
gcc 6.3, for example, gives error messages centered around Typo
being an incomplete type, including
/usr/include/c++/6/bits/stl_vector.h:161:9: error: invalid use of incomplete type ‘struct main()::Typo
’
#include <vector>
int main() {
std::vector<Typo> b; // Errors centred around `Typo` not being defined
}
gcc 6.3, for example, gives errors centered around Typo
not being defined, including
prog.cpp:4:14: error: ‘Typo’
was not declared in this scope
Both vector instantiations are errors of course, but what is the rationale for the differing diagnostic messages as cited in the program comments?
struct Typo
is an elaborated type specifier. That affects how name lookup works.
[basic.lookup.elab]
2: If the elaborated-type-specifier has no nested-name-specifier,
and unless the elaborated-type-specifier appears in a declaration with
the following form:
class-key attribute-specifier-seq identifier ;
the identifier is looked up according to [basic.lookup.unqual] but
ignoring any non-type names that have been declared. If the
elaborated-type-specifier is introduced by the enum keyword and this
lookup does not find a previously declared type-name, the
elaborated-type-specifier is ill-formed. If the
elaborated-type-specifier is introduced by the class-key and this
lookup does not find a previously declared type-name, or if the
elaborated-type-specifier appears in a declaration with the form:
class-key attribute-specifier-seq identifier ;
the elaborated-type-specifier is a declaration that introduces the
class-name as described in [basic.scope.pdecl].
So in std::vector<struct Typo> a;
, because struct Typo
does not find a previously declared Typo
, it serves as a forward declaration for the type. And as such, its the vector instantiation that may1 complain the type it got is incomplete because it will try to do stuff with it.
While in std::vector<Typo> b;
, looking up Typo
finds nothing. There is no previous declaration for it, so its at this point a diagnostic should be issued that this identifier is undeclared.
1 - Depends on what standard you are compiling to, and what members of the vector you are using. Support for incomplete types has been added.