gpt4 book ai didi

c++ - 从属名称的模板消歧器

转载 作者:行者123 更新时间:2023-12-01 17:43:26 26 4
gpt4 key购买 nike

我在编译以下示例时遇到了以下问题:

template <int N>
class Matrix {
public:
template <int Idx>
int head() {
return Idx;
}
};

template <typename T>
class Test {
static constexpr int RayDim = 3;
public:
int func() const {
Matrix<RayDim> yF;
return yF.head<1>();
// ^ is template keyword required here?
}
};

struct Empty {};

void test() {
Test<Empty> t;
}

链接到编译器资源管理器: https://godbolt.org/z/js4XaP

该代码可以使用 GCC 9.2 和 MSVC 19.22 进行编译,但不能使用 clang 9.0.0 进行编译。 Clang 声明需要模板关键字。如果static constexpr int RayDim = 3;移入int func() const clang 接受它。

正如代码块中的注释所述, yF.head<1>() 所需的模板关键字是?

最佳答案

template这里不应需要关键字,因此 clang 拒绝该程序是不正确的。

下面的所有 C++ 标准章节和段落编号以及引用对于 C++17 草案 N4659 和当前链接的 C++20 草案都是相同的。

template 的要求在.之后或->::命名成员模板时的 token 位于 [temp.names]/4 。该段落首先列出不允许使用该关键字的情况,然后列出该关键字是可选的且没有区别的情况,然后:

In all other contexts, when naming a template specialization of a member of an unknown specialization ([temp.dep.type]), the member template name shall be prefixed by the keyword template.

“未知特化的成员”是不是“当前实例化”的依赖类型的成员。所以问题是 Matrix<RayDim> 是否是依赖类型。为此,我们查看 [temp.dep.type]/9:

A type is dependent if it is

  • a template parameter,
  • a member of an unknown specialization,
  • a nested class or enumeration that is a dependent member of the current instantiation,
  • a cv-qualified type where the cv-unqualified type is dependent,
  • a compound type constructed from any dependent type,
  • an array type whose element type is dependent or whose bound (if any) is value-dependent,
  • a function type whose exception specification is value-dependent,
  • a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion, or
  • denoted by decltype(expression), where expression is type-dependent.

Matrix<RayDim>显然不是模板参数、任何类型的成员、cv 限定的、数组类型、函数类型或 decltype 指定的。它是一种复合类型,但它仅使用模板名称和表达式,因此不是从任何其他类型构造的。

剩下了simple-template-id的情况。模板名称Matrix不是模板参数。模板参数 RayDim是一个表达式,所以现在看看它是类型相关的还是值相关的。

“类型相关”在 [temp.dep.expr] 中定义。 。只有第 3 段可以适用于单独的标识符,例如 RayDim :

An id-expression is type-dependent if it contains

  • an identifier associated by name lookup with one or more declarations declared with a dependent type,
  • an identifier associated by name lookup with a non-type template-parameter declared with a type that contains a placeholder type,
  • an identifier associated by name lookup with a variable declared with a type that contains a placeholder type ([dcl.spec.auto]) where the initializer is type-dependent,
  • an identifier associated by name lookup with one or more declarations of member functions of the current instantiation declared with a return type that contains a placeholder type,
  • an identifier associated by name lookup with a structured binding declaration whose brace-or-equal-initializer is type-dependent,
  • the identifier __func__ ([dcl.fct.def.general]), where any enclosing function is a template, a member of a class template, or a generic lambda,
  • a template-id that is dependent,
  • a conversion-function-id that specifies a dependent type, or
  • a nested-name-specifier or a qualified-id that names a member of an unknown specialization;

or if it names a dependent member of the current instantiation that is a static data member of type "array of unknown bound of T" for some T ([temp.static]).

RayDim当然不包含任何__func__模板 ID转换函数 ID嵌套名称说明符限定 ID。名称查找查找类模板的静态成员声明。 RayDim 的声明当然不是模板参数、成员函数或结构化绑定(bind)声明,其类型 const int当然不是依赖类型或数组类型,并且不包含占位符类型。所以RayDim不依赖于类型。

“值相关”在 [temp.dep.constexpr] 中定义。 。唯一可以应用于像 RayDim 这样的单独标识符的情况在第 2 段中:

An id-expression is value-dependent if:

  • it is type-dependent,
  • it is the name of a non-type template parameter,
  • it names a static data member that is a dependent member of the current instantiation and is not initialized in a member-declarator,
  • it names a static member function that is a dependent member of the current instantiation, or
  • it is a constant with literal type and is initialized with an expression that is value-dependent.

从上面,RayDim不依赖于类型。它当然不是模板参数或成员函数。它是一个静态数据成员,也是当前实例化的依赖成员,但它是在成员声明符中初始化的。也就是说,“= 3 ”出现在类定义中,而不是单独的成员定义中。它是一个字面量类型的常量,但它的初始值设定项 3不依赖于值。

所以RayDim不依赖于值或类型。因此Matrix<RayDim>不是依赖类型,yF.head不是未知实例化的成员,并且 template head之前的关键字是可选的,不是必需的。 (这是允许的,因为它不在“仅类型上下文”中,并且 head 实际上命名了成员模板。)

关于c++ - 从属名称的模板消歧器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58844714/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com