gpt4 book ai didi

c++ - 推导(非类型)模板参数类型的编译器差异

转载 作者:行者123 更新时间:2023-12-04 08:14:29 27 4
gpt4 key购买 nike

考虑以下示例:

#include <type_traits>

struct A {};

template <A const i> void f() {
static_assert(std::is_same_v<decltype(i), A const>); // #1
A& ar = i; // #2
}

int main() {
f<A{}>();
}
Clang(1) 和 GCC(1) 都拒绝了以下两个看似相互冲突的错误:
#1 error: static_assert failed due to requirement 'std::is_same_v<A, const A>'
#2 error: binding reference of type 'A' to value of type 'const A' drops 'const' qualifier

GCC demo , Clang demo .
此外,如果我们将非类型模板参数的类型更改为占位符类型,如下所示:
template <auto const i> void g() { 
static_assert(std::is_same_v<decltype(i), A const>); // #1
A& ar = i; // #2
}
然后 GCC 接受 #1 ,而 Clang 拒绝它(都拒绝 #2 如上所述)。
GCC demo , Clang demo .
这里发生了什么,哪个编译器是正确的(如果有的话)?

(1) GCC HEAD 11.0.0 20210117 和 Clang HEAD 12.0.0 (20210118), -std=c++20 .

最佳答案

GCC 和 Clang 都(可能)正确地为 #1 发出错误。和 #2对于 f .
根据 [temp.param]/6 [ 重点矿]:

A non-type template-parameter shall have one of the following(possibly cv-qualified) types:

  • (6.1) a structural type (see below),
  • (6.2) a type that contains a placeholder type ([dcl.spec.auto]), or
  • (6.3) a placeholder for a deduced class type ([dcl.type.class.deduct]).

The top-level cv-qualifiers on the template-parameter are ignoredwhen determining its type.


顶级 cv 限定符在确定其类型时被忽略;与处理需要推导的占位符类型的 (6.2) 和 (6.3) 相比,对于 (6.1) 的“确定”所指的内容可以说有些模糊。
[dcl.type.decltype]/1 [ 重点矿]:

For an expression E, the type denoted by decltype(E) is defined asfollows:

  • [...]
  • otherwise, if E is an unparenthesized id-expression naming a non-type template-parameter, decltype(E) is the type of thetemplate-parameter after performing any necessary type deduction([dcl.spec.auto], [dcl.type.class.deduct]);
  • [...]

提到 decltype(i) 的类型在 f是非类型模板参数的类型,在执行任何必要的类型推导后,后跟两个连接到 [temp.param]/6.2 和 [temp.param]/6.3 的引用。 #1 的 key 在 f因此是 [temp.param]/6.1 是否也经历“确定其类型”,即使它被明确注释为 A const (无需扣除)。 GCC 和 Clang 似乎都同意这种情况: A const经历“类型确定”和 const已移除。

了解 #2f更直接;与非类型模板参数(类类型)关联的实际模板参数对象 A不一定与非类型模板参数类型相同;相反,它的类型由 [temp.param]/8 控制[ 重点矿]:

An id-expression naming a non-type template-parameter of class type T denotes a static storage duration object of type const T, known as a template parameter object, whose value is that of the corresponding template argument after it has been converted to the type of the template-parameter. All such template parameters in the program of the same type with the same value denote the same template parameter object. A template parameter object shall have constant destruction ([expr.const]). [ Note: If an id-expression names a non-type non-reference template-parameter, then it is a prvalue if it has non-class type. Otherwise, if it is of class type T, it is an lvalue and has type const T ([expr.prim.id.unqual]). — end note ]


这样任何类类型的模板参数对象 T总是有类型 const T ,从而解释了 #2 处的错误.请注意,后者仅适用于类类型,因为命名非类型非引用模板参数的 id 表达式是纯右值。

至于 #1 的 GCC 和 Clang 之间的差异在 g ,在应用 [temp.param]/6 时,特别是 [temp.param]/6.2,应用类型推导同时忽略模板参数上的 cv 限定符时没有含糊之处。含义 decltype(i)Ag ,并且 GCC 错误地接受行 #1 .我已相应地提交了以下 GCC 错误报告:
  • Bug 98820 - Placeholder (auto) non-type template parameter wrongly deduced to 'const' for class type arguments
  • 关于c++ - 推导(非类型)模板参数类型的编译器差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65779069/

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