Will a class that is declared within a member initializer of a constructor of another class be visible outside it?

  • A+
Category:Languages

Consider the following piece of code:

struct Foo {      void* p;      Foo() : p{(class Bar*)0} {} };  Bar* bar; 

The latest versions of GCC (8.2) and Clang (7.0.0) fail to compile it. So does ICC (19.0.1).
However MSVC (v19.16) compiles it cleanly.

The error from GCC is: error: 'Bar' does not name a type; did you mean 'char'?
Clang and ICC issue similar messages.

Conformance viewer for all four compilers at godbolt.

So which of the compiler(s) is correct as per the standard?

 


  • [basic.lookup.elab] ... If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name ... the elaborated-type-specifier is a declaration that introduces the class-name as described in [basic.scope.pdecl]

  • [basic.scope.pdecl] - for an elaborated-type-specifier of the form

    class-key identifier

    if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope [does not apply because of scope], ... otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration.

Now, the tricky bit. Is the member initialiser list "contained" in the scope of the constructor or not? If not, then the smallest block or namespace scope is the global namespace and the program would be well-formed. If yes, then the smallest scope is the block scope of the constructor, and thus the class would not be declared in the global scope.

As far as I can tell, there is no rule saying that mem-init-list is "contained in the block scope of the constructor". It is outside the curly brackets that delimit the scope. As such, the program is well-formed.


There's this bit:

- [class.base.init] Names in the expression-list or braced-init-list of a mem-initializer are evaluated in the scope of the constructor for which the mem-initializer is specified. ...

Perhaps one could interpret that "evaluated" implies "contained" for the purpose of declarations - I don't think so, but I could be wrong.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: