#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.
4
1 Answer
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 liketemplate<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.
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.
14 hours ago
@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.
14 hours ago
@HolyBlackCat Ah, good point, here the nested class is inside a function, so it's not even a duplicate.
14 hours ago
I think is about lexical. Complier think
B
ofA::B
is static member. But we can fix by add explicit markstd::is_class_v<typename A::B>
.13 hours ago