Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the rationale behind the differences between the compiler diagnostics issued when it sees std::vector<Typo> and std::vector<struct Typo>

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?

like image 881
Bathsheba Avatar asked Jan 31 '19 12:01

Bathsheba


1 Answers

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.

like image 124
StoryTeller - Unslander Monica Avatar answered Sep 29 '22 07:09

StoryTeller - Unslander Monica