c++templateslanguage-lawyerinner-classeslocal-class

Necessity of `typename` for naming of local nested classes in function templates


I have a function template f, defining in its body a local class A with another nested class B. Both classes are not templates. Must I name the inner class as typename A::B or shorter variant A::B is ok as well?

Here is the simplified code:

template<class T>
void f() {
    struct A{ struct B{}; };

    // ok everywhere
    auto b = typename A::B();
    b = typename A::B{};

    // ok in EDG and MSVC
    b = A::B();

    // ok in EDG only
    b = A::B{};
}

int main() {
    f<int>();
}
error: missing 'typename' prior to dependent type name 'A::B'
error: dependent-name 'f()::A::B' is parsed as a non-type, but instantiation yields a type
error: expected ';' after expression
error: expected ';' before '{' token [-Wtemplate-body]
error C2760: syntax error: '{' was unexpected here; expected 'expression'

Online demo

Which implementation is correct here?


Solution

  • Core issue 2936, which is fairly recent, made typename not required when naming a (type) member of a local class. This resolution is a Defect Report, which will become official when C++26 is published and will also be considered to apply to older language versions.

    The standard uses a broad brush when painting names as dependent. Some of those names don't really depend on the template arguments, but in terms of specification, it's more correct to make too many names dependent than too few (because if something should be dependent and isn't, then compilers will have difficulty with parsing it if the user isn't required to use typename). However, if there's an obvious category of names that shouldn't be dependent but are, it's a usability issue and should be corrected. That is what was done in this case (26 years after the original C++ standard was published).