本地类中的依赖名称

Mak*_* S. 19 c++ language-lawyer

#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>();
}
Run Code Online (Sandbox Code Playgroud)

为什么是A::B从属名称而A不是?在标准中看不到任何相关内容。

dfr*_*fri 17

这是CWG 2074,仍未解决 [重点是我的]:

2074. 函数模板局部类的类型依赖

根据 13.8.3.2 [temp.dep.type] 第 9 段,函数模板中的局部类当且仅当它包含依赖类型的子对象时才是依赖的。然而,给出一个像这样的例子

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

#1 的处理存在实现差异,但是否定义 DEPENDENT 似乎没有区别。

[...]

也许正确的答案是,类型应该是相关的,但是是当前实例化的成员,允许在没有类型名的情况下进行名称查找。

附加说明(2022 年 9 月):

目前,术语“当前实例化”仅针对类模板定义,因此不适用于函数模板

此外,该问题的解决方案还应处理本地枚举,特别注意 9.7.2 [enum.udecl] 第 1 段:

详细枚举说明符不应命名依赖类型并且...如果本地枚举被设为依赖类型,则此规则(未经修改)将不允许以下合理示例:

template <class T>
void f() {
  enum class E { e1, e2 };
  using enum E;
}
Run Code Online (Sandbox Code Playgroud)

该规范似乎未明确规定,因为供应商似乎(在实现差异的基础上)强制执行[temp.dep.type]/7.3 [重点是我的]:

/7 一个类型是相关的,如果它是

  • [...]
  • /7.3嵌套类或枚举是当前实例化类的直接成员,

但正如 CWG 2074 中所述,根据[temp.dep.type]/1 的当前实例化并未涵盖函数模板情况的实际规则。