303*_*303 8 c++ dependent-name language-lawyer compiler-bug c++20
考虑到以下代码示例,我希望必须template在此处使用关键字来指导编译器将变量视为v模板。然而,MSVC 拒绝使用该template关键字,而 Clang 和 GCC 实际上需要它。在这种情况下,C++20 标准中的哪条具体规则强制或禁止使用关键字template?
struct s {
template<typename...>
static constexpr auto v = true;
};
// all ok
static_assert([](auto x){ return decltype(x)::template v<>; }(s{}));
// clang ok, gcc ok, msvc nope
static_assert([](auto x){ return x.template v<>; }(s{}));
// clang nope, gcc nope, msvc ok
static_assert([](auto x){ return x.v<>; }(s{}));
Run Code Online (Sandbox Code Playgroud)
来自 Clang 的错误消息:
<source>:10:36: error: use 'template' keyword to treat 'v'
as a dependent template name
10 | static_assert([](auto x){ return x.v<>; }(s{}));
| ^
| template
Run Code Online (Sandbox Code Playgroud)
来自 MSVC 的错误消息:
<source>(8): error C2187: syntax error: 'template' was unexpected here
<source>(8): note: see reference to function template instantiation
'auto <lambda_2>::operator ()<s>(_T1) const' being compiled
with
[
_T1=s
]
Run Code Online (Sandbox Code Playgroud)
In short, x and decltype(x) are dependent, and template is allowed and necessary in all cases. There is an MSVC compiler bug.
至于依赖类型,包括decltype:
一个类型是依赖的,如果它是:
- 模板参数,
- [...]
- 用 表示
decltype(expression),其中expression与类型相关。
此外,x是类型相关的,因为(参见[temp.dep.expr] p3.1)它是:
通过名称查找与使用依赖类型声明的一个或多个声明相关联
泛型 lambda 的参数auto使调用运算符成为函数模板,因此很自然地x与模板参数相关联,而模板参数是相关的。因此template对于 来说是必要的decltype(x)::template v<>。所有编译器都同意,这是正确的。
在声明中
Run Code Online (Sandbox Code Playgroud)return x.template v<>;
x是类型相关的,因为它通过名称查找与泛型 lambda 调用运算符的隐式模板参数相关联。因此,template是必要的。
注意:除了标准语言之外,直观上这是必要的,因为如果不知道这是一个模板,x.v <则可能会被解释为“x.v小于...” 。v这在[temp.names] p3中正式说明。
另请参阅:在哪里以及为什么必须放置“template”和“typename”关键字?
MSVC 不允许这一事实.template v<>显然是一个错误。值得注意的是,MSVC 确实接受:
[](s x){ return x.template v<>; }(s{})
Run Code Online (Sandbox Code Playgroud)
但是,使用autonot 作为s参数类型会导致编译器错误。这根本没有意义,因为template和typename是可选的,不必要地添加它们永远不会导致失败。
注意:我无法在Microsoft 开发人员社区中找到现有的错误报告,因此可能尚未报告此问题。您可能想要报告此错误。
| 归档时间: |
|
| 查看次数: |
341 次 |
| 最近记录: |