Dependent name in local class

Dependent name in local class


12

#include <type_traits>

template<typename... Ts>
void boo()
{
    struct A
    {
        struct B {};
    };
    static_assert(std::is_class_v<A>);
    static_assert(std::is_class_v<A::B>); // compilation failure; need typename.
}

int main()
{
    boo<int>();
}

Why is A::B a dependent name and A is not?
Can not see anything in standard about that.

New contributor

Maksim S. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

4

  • 1

    Basically the same question as stackoverflow.com/questions/49226871, but it was closed with the wrong target. The template-typename canonical doesn't cover this afaict.

    – cigien

    14 hours ago

  • 1

    @cigien That Q is different. Nested class (outside of function) can be specialized, that's why it's dependent. In this case you can't reference the classes to specialize them (I think?), so this looks like a defect to me.

    – HolyBlackCat

    14 hours ago


  • @HolyBlackCat Ah, good point, here the nested class is inside a function, so it's not even a duplicate.

    – cigien

    14 hours ago

  • 1

    I think is about lexical. Complier think B of A::B is static member. But we can fix by add explicit mark std::is_class_v<typename A::B> .

    – Jakkapong Rattananen

    13 hours ago


1 Answer
1


10

This is CWG 2074, which is still unresolved [emphasis mine]:

2074. Type-dependence of local class of function template

According to 13.8.3.2 [temp.dep.type] paragraph 9, a local class in a
function template is dependent if and only if it contains a subobject
of a dependent type. However, given an example like

  template<typename T> void f() {
    struct X {
      typedef int type;
  #ifdef DEPENDENT
      T x;
  #endif
    };
  X::type y;    // #1
  }
  void g() { f<int>(); }

there is implementation variance in the treatment of #1, but whether
or not DEPENDENT is defined appears to make no difference.

[…]

Perhaps the right answer is that the types should be dependent but a member of the current instantiation, permitting name lookup without typename.

Additional notes (September, 2022):

At present, the term "current instantiation" is defined for class
templates only, and thus does not apply to function templates
.

Moreover, the resolution for this issue should also handle local
enums, with particular attention to 9.7.2 [enum.udecl] paragraph 1:

The elaborated-enum-specifier shall not name a dependent type and…
This rule, without amendment, would disallow the following reasonable
example if local enums were made dependent types:

template <class T>
void f() {
  enum class E { e1, e2 };
  using enum E;
}

The spec appears underspecified, as vendors seems to (on an implementation variance basis) enforce [temp.dep.type]/7.3 [emphasis mine]:

/7 A type is dependent if it is

  • […]
  • /7.3 a nested class or enumeration that is a direct member of a class that is the current instantiation,

But as noted in CWG 2074, current instantiation as per [temp.dep.type]/1 does not cover what are actually the rules for the case of function templates.



Leave a Reply

Your email address will not be published. Required fields are marked *