提问人:303 提问时间:9/20/2023 最后编辑:Jan Schultke303 更新时间:9/21/2023 访问量:161
在依赖模板名称之前使用 template 关键字
Use of template keyword before dependent template name
问:
考虑到下面的代码示例,我希望必须在此处使用关键字来指导编译器将变量视为模板。但是,MSVC 拒绝使用关键字,而 Clang 和 GCC 实际上需要它。在这种情况下,C++ 标准中的哪条特定规则强制或禁止使用关键字?template
v
template
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{}));
来自 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
来自 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
]
答:
简而言之,并且是依赖性的,并且在所有情况下都是允许和必要的。存在 MSVC 编译器错误。x
decltype(x)
template
C++ 标准措辞
至于依赖类型,包括:decltype
如果类型符合以下条件,则类型是依赖的:
- 模板参数,
- [...]
- 用 表示,其中与类型相关。
decltype(expression)
expression
此外,与类型相关,因为(参见 [temp.dep.expr] p3.1)它是:x
通过名称查找与使用依赖类型声明的一个或多个声明相关联
泛型 lambda 的参数使调用运算符成为函数模板,因此自然而然地与模板参数相关联,该参数是依赖的。
因此,对于 是必要的。所有编译器都同意,这是正确的。auto
x
template
decltype(x)::template v<>
在声明中
return x.template v<>;
x
与类型相关,因为它通过名称查找与泛型 Lambda 的调用运算符的隐式模板参数相关联。因此,是必要的。template
注意:除了标准之外,这在直觉上是必要的,因为如果不知道 v
是模板,则 x.v <可以解释为“x.v
小于...”。
这在 [temp.names] p3 中正式说明。
Смотритетакже: 我必须在哪里以及为什么必须放置“模板”和“typename”关键字?
MSVC 编译器错误
MSVC 不允许的事实显然是一个错误。值得注意的是,MSVC 确实接受:.template v<>
[](s x){ return x.template v<>; }(s{})
但是,使用 instead 而不是作为参数类型会导致编译器错误。这完全没有意义,因为 和 是可选的,不必要地添加它们永远不会导致失败。auto
s
template
typename
注意:我无法在 Microsoft 开发人员社区中找到现有的错误报告,因此可能尚未报告。您可能需要报告此错误。
评论
模板
是必要的”的引用。我什至找不到涉及模棱两可主题的引述。template_name < template_parameter_list > ...
( template_name < template_parameter_list ) > ...
template
<
template
<
/3
评论
(auto x)
(s x)
auto
s
x
s
[basic.lookup.qual.general]/3
是如何回答的。.template v<>
p->X<0>::f(); // error: A::X not found in ((p->X) < 0) > ::f()